WITH

Introduction

The WITH clause enables you to manipulate the output before it is passed to subsequent parts of the query. This manipulation may change the shape and/or number of records in the result set.

Like RETURN, WITH supports column aliasing to introduce expressions into the result stream.

WITH also separates graph reads from graph writes. Each part of a Cypher query must be either read-only or write-only. An optional WITH clause is required when transitioning from a write clause (e.g., CREATE, SET, REMOVE) to a read clause (e.g., MATCH, WHERE).

In YMatrix AGE, common use cases for WITH include:

  1. Intermediate processing ("pipeline")
    WITH acts as an intermediate pipeline stage: it transforms the results of the preceding clause before passing them forward.
    Example:
    MATCH (p:Person) WITH p ORDER BY p.age DESC LIMIT 3 RETURN p.name
    First matches all Person vertices; WITH sorts them by age and limits to the top three; finally, RETURN emits only the name. Without WITH, RETURN cannot perform such intermediate filtering.

  2. Column aliasing (similar to RETURN)
    WITH assigns aliases to expressions for use in subsequent clauses.
    Example:
    MATCH (p:Person) WITH p.name AS name, p.age AS age WHERE age > 30 RETURN name
    The WITH clause renames properties, allowing later clauses to reference them by their new names.

  3. Read/write separation
    Per Cypher semantics, a query fragment must be either read-only or write-only. CREATE is a write operation; MATCH and WHERE are read operations. To chain write and read operations, WITH is mandatory.
    Example:
    CREATE (a:Person {name: 'Tom'}) WITH a MATCH (a)-[:KNOWS]->(b) RETURN b
    Omitting WITH a would cause an error — direct transition from CREATE to MATCH violates the read/write isolation rule.

  4. Global ordering
    In YMatrix AGE, ORDER BY alone does not guarantee globally ordered results across segments. Therefore, ORDER BY + LIMIT does not guarantee the top N results from the entire dataset.
    To ensure global ordering, apply ORDER BY after a WITH clause — which triggers data motion (a gather operation) to consolidate rows onto a single segment before sorting and limiting.

    • RETURN p ORDER BY p.age LIMIT 3: Each segment sorts and limits locally → final result is not guaranteed to be the global top 3.
    • WITH p ORDER BY p.age LIMIT 3 RETURN p: WITH induces motion; global sort and limit occur after consolidation.

Filtering Aggregation Results

Aggregated values can only be filtered using a WITH clause.

Query

SELECT *
FROM cypher('graph_name', $$
    MATCH (david {name: 'David'})-[]-(otherPerson)-[]->()
    WITH otherPerson, count(*) AS foaf
    WHERE foaf > 1
    RETURN otherPerson.name
$$) AS (name agtype);

Returns the names of persons connected to 'David' who have more than one outgoing relationship.

Result

name
"Anders"
(1 row)

Sorting Before collect

You can sort results before passing them to collect, thereby producing a sorted list.

Query

SELECT *
FROM cypher('graph_name', $$
    MATCH (n) WITH n
    ORDER BY n.name DESC LIMIT 3
    RETURN collect(n.name)
$$) AS (names agtype);

Returns a list of up to three person names, sorted in descending lexicographic order.

Result

names
["Emil","David","Ceasar"]
(1 row)

Limiting Branches in Path Search

You can match paths, apply a LIMIT to restrict the number of matched paths, and then use those limited results as input for further pattern matching — including additional bounded searches.

Query

SELECT *
FROM cypher('graph_name', $$
    MATCH (n {name: 'Anders'})-[]-(m) WITH m
    ORDER BY m.name DESC LIMIT 1
    MATCH (m)-[]-(o)
    RETURN o.name
$$) AS (name agtype);

Finds all nodes connected to 'Anders', sorts them by name in descending order, selects the first, then finds all nodes connected to that node and returns their names.

Result

name
"Anders"
"Bossman"
(2 rows)