10.5. With

The WITH clause allows query parts to be chained together, piping the results from one to be used as starting points or criteria in the next.

Using WITH, you can manipulate the output before it is passed on to the following query parts. The manipulations can be of the shape and/or number of entries in the result set.

One common usage of WITH is to limit the number of entries that are then passed on to other MATCH clauses. By combining ORDER BY and LIMIT, it’s possible to get the top X entries by some criteria, and then bring in additional data from the graph.

Another use is to filter on aggregated values. WITH is used to introduce aggregates which can then by used in predicates in WHERE. These aggregate expressions create new bindings in the results. WITH can also, like RETURN, alias expressions that are introduced into the results using the aliases as binding name.

WITH is also used to separate reading from updating of the graph. Every part of a query must be either read-only or write-only. When going from a writing part to a reading part, the switch must be done with a WITH clause.

Figure 10.5. Graph

Filter on aggregate function results

Aggregated results have to pass through a WITH clause to be able to filter on.

Query 

MATCH (david { name: "David" })--(otherPerson)-->()
WITH otherPerson, count(*) AS foaf
WHERE foaf > 1
RETURN otherPerson

The person connected to David with the at least more than one outgoing relationship will be returned by the query.

Result

otherPerson
1 row

Node[0]{name:"Anders"}

Try this query live create (_0 {`name`:"Anders"}) create (_1 {`name`:"Bossman"}) create (_2 {`name`:"Ceasar"}) create (_3 {`name`:"David"}) create (_4 {`name`:"Emil"}) create (_0)-[:`BLOCKS`]->(_2) create (_0)-[:`KNOWS`]->(_1) create (_1)-[:`BLOCKS`]->(_3) create (_1)-[:`KNOWS`]->(_4) create (_2)-[:`KNOWS`]->(_4) create (_3)-[:`KNOWS`]->(_0) ; match (david {name: "David"})--(otherPerson)-->() with otherPerson, count(*) as foaf where foaf > 1 return otherPerson

Sort results before using collect on them

You can sort your results before passing them to collect, thus sorting the resulting list.

Query 

MATCH (n)
WITH n
ORDER BY n.name DESC LIMIT 3
RETURN collect(n.name)

A list of the names of people in reverse order, limited to 3, in a list.

Result

collect(n.name)
1 row

["Emil","David","Ceasar"]

Try this query live create (_0 {`name`:"Anders"}) create (_1 {`name`:"Bossman"}) create (_2 {`name`:"Ceasar"}) create (_3 {`name`:"David"}) create (_4 {`name`:"Emil"}) create (_0)-[:`BLOCKS`]->(_2) create (_0)-[:`KNOWS`]->(_1) create (_1)-[:`BLOCKS`]->(_3) create (_1)-[:`KNOWS`]->(_4) create (_2)-[:`KNOWS`]->(_4) create (_3)-[:`KNOWS`]->(_0) ; match (n) with n order by n.name desc limit 3 return collect(n.name)