WITH

WITH 子句允许将查询部分链接在一起,将一个部分的结果作为下一个部分的起点或条件进行传递。

需要注意的是,WITH 会影响范围内的变量。任何未包含在 WITH 子句中的变量都不会传递到查询的其余部分。可以使用通配符 * 来包含当前范围内所有变量。

使用 WITH,可以在结果集传递到后续查询部分之前对其进行操作。操作可以是对结果集形状和/或条目数量进行修改。

WITH 的一个常见用法是限制传递到其他 MATCH 子句的条目数量。通过结合 ORDER BYLIMIT,可以根据某些条件获取前 X 个条目,然后从图中引入其他数据。

WITH 还可以用于引入新的变量,这些变量包含用于后续查询部分的表达式的结果(参见为表达式引入变量)。为了方便起见,通配符 * 会扩展到当前范围内所有变量,并将它们传递到下一个查询部分(参见使用通配符传递变量)。

另一个用途是对聚合值进行过滤。WITH 用于引入聚合,然后可以在 WHERE 中的谓词中使用这些聚合。这些聚合表达式会在结果中创建新的绑定。

WITH 也用于将读取操作与更新操作分开。查询的每个部分必须是只读或只写。从写入部分到读取部分时,必须使用 WITH 子句进行切换。

graph with clause

为表达式引入变量

可以为表达式求值的結果引入新的变量。

查询
MATCH (george {name: 'George'})<--(otherPerson)
WITH otherPerson, toUpper(otherPerson.name) AS upperCaseName
WHERE upperCaseName STARTS WITH 'C'
RETURN otherPerson.name

此查询返回与 'George' 相连且姓名以 C 开头的所有人的姓名,不区分大小写。

表 1. 结果
otherPerson.name

"Caesar"

行数:1

使用通配符传递变量

可以使用通配符 * 传递范围内的所有变量,以及引入新的变量。

查询
MATCH (person)-[r]->(otherPerson)
WITH *, type(r) AS connectionType
RETURN person.name, otherPerson.name, connectionType

此查询返回所有相关人员的姓名以及他们之间的关系类型。

表 2. 结果
person.name otherPerson.name connectionType

"David"

"Anders"

"KNOWS"

"Anders"

"Bossman"

"KNOWS"

"Anders"

"Caesar"

"BLOCKS"

"Bossman"

"David"

"BLOCKS"

"Bossman"

"George"

"KNOWS"

"Caesar"

"George"

"KNOWS"

行数:6

对聚合函数结果进行过滤

必须通过 WITH 子句才能对聚合结果进行过滤。

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

此查询返回与 'David' 相连且具有至少两个以上传出关系的人员的姓名。

表 3. 结果
otherPerson.name

"Anders"

行数:1

在对结果使用 collect 之前对其进行排序

可以在将结果传递给 collect 之前对它们进行排序,从而对结果列表进行排序。

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

此查询返回一个列表,该列表包含按反序排序的人员姓名,并限制为 3 个。

表 4. 结果
collect(n.name)

["George","David","Caesar"]

行数:1

可以匹配路径,将其限制为一定数量,然后使用这些路径作为基础再次进行匹配,以及任意数量的类似限制搜索。

查询
MATCH (n {name: 'Anders'})--(m)
WITH m
ORDER BY m.name DESC
LIMIT 1
MATCH (m)--(o)
RETURN o.name

'Anders' 开始,查找所有匹配的节点,按姓名降序排序,并获取最上面的结果,然后查找与该最上面结果相连的所有节点,并返回它们的姓名。

表 5. 结果
o.name

"Anders"

"Bossman"

行数:2

限制和过滤

可以在同一个 WITH 子句中限制和过滤。请注意,LIMIT 子句是在 WHERE 子句之前应用的。

查询
UNWIND [1, 2, 3, 4, 5, 6] AS x
WITH x
LIMIT 5
WHERE x > 2
RETURN x

首先应用限制,将行数减少到列表中的前 5 项。然后应用过滤器,减少最终结果,如下所示

表 6. 结果
x

3

4

5

行数:3

如果想要先过滤再限制,则需要在单独的步骤中进行过滤

查询

UNWIND [1, 2, 3, 4, 5, 6] AS x
WITH x
WHERE x > 2
WITH x
LIMIT 5
RETURN x

这次先应用过滤器,将行数减少到 [3, 4, 5, 6] 列表。然后应用限制。由于限制大于剩余行的总数,因此返回所有行。

表 7. 结果
x

3

4

5

6

行数:4