WITH

更新时间:
复制 MD 格式

WITH acts as a pipeline between query stages: it takes the output of one stage, optionally transforms or filters it, and passes the result to the next stage.

WITH serves the following purposes:

  • Create aliases for expressions (like RETURN)

  • Filter on aggregate function results

  • Sort results before passing them to collect()

  • Limit branching in multi-hop path searches

  • Separate read clauses from write clauses in the same query

How it works

In a Cypher query executed via the cypher() function, each clause passes its output to the next. WITH gives you explicit control over that handoff — you decide which variables carry forward, under what names, and in what order or quantity.

Any variable not listed in a WITH clause is dropped from scope and unavailable to subsequent clauses.

Filter on aggregate function results

To filter on the result of an aggregate function such as count(), pass the aggregation through WITH first, then apply WHERE.

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

Result:

   name
----------
"Anders"
(1 row)

WHERE cannot filter directly on foaf in a MATCH clause because aggregate values only exist after grouping. WITH materializes the aggregation, making it available for filtering.

Sort results before collecting

To produce a sorted list with collect(), sort results using ORDER BY in a WITH clause before the collect() call.

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

Result:

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

collect() preserves the order of its input, so sorting before collecting determines the order of elements in the output list.

Limit branching of a path search

Use WITH to cap intermediate results before continuing traversal. This prevents combinatorial explosion when exploring multi-hop paths.

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);

Result:

   name
----------
"Anders"
"Bossman"
(2 rows)

Starting at Anders, the first MATCH finds all directly connected nodes. WITH m ORDER BY m.name DESC LIMIT 1 keeps only the top result. The second MATCH then traverses from that single node and returns its neighbors.

Separate read and write clauses

Every part of a Cypher query must be either read-only or write-only. When transitioning from a write clause to a read clause, use WITH to bridge the two.

SELECT *
FROM cypher('graph_name', $$
    CREATE (n:Person {name: 'Frank'})
    WITH n
    MATCH (n)-[]-(neighbor)
    RETURN neighbor.name
$$) AS (name agtype);

Without WITH, mixing CREATE and MATCH in the same query stage is not permitted.