查询由多个子句链接在一起组成。这些子句将在“子句”一章中详细讨论。
整个查询的语义由其子句的语义定义。每个子句的输入都是图的状态和由当前变量组成的中间结果表。一个子句的输出是图的新状态和新的中间结果表,作为下一个子句的输入。第一个子句将查询前的图的状态和一个空的中间结果表作为输入。最后一个子句的输出是查询的结果。
|
除非使用ORDER BY,否则 Neo4j 不保证查询结果的行顺序。 |
本节使用以下示例图。

现在遵循以下查询的中间结果表和每个子句后的图形状态:
MATCH (john:Person {name: 'John'})
MATCH (john)-[:FRIEND]->(friend)
RETURN friend.name AS friendName
该查询仅具有读取子句,因此图的状态保持不变,因此下面将其省略。
| 条款 | 该条款后的中间结果表 | ||||||
|---|---|---|---|---|---|---|---|
匹配(约翰:人 {名称:'约翰'})
|
| ||||||
匹配 (约翰)-[:朋友]->(朋友)
|
| ||||||
返回 friend.name 作为 friendName
|
|
上面的例子只研究了允许线性组合和省略 write 子句的子句。下一节将探讨这些非线性组合和 write 子句。
读写查询
在 Cypher 查询中,读取和写入子句可以轮流执行。读写查询最重要的方面是图的状态也会在子句之间发生变化。
|
一个子句永远不能观察到后面子句的写入。 |
使用与上面相同的示例图,此示例显示以下查询的每个子句之后的中间结果表和图的状态:
MATCH (j:Person) WHERE j.name STARTS WITH "J"
CREATE (j)-[:FRIEND]->(jj:Person {name: "Jay-jay"})
该查询查找所有属性name以“J”开头的节点,并为每个这样的节点创建另一个属性name设置为“Jay-jay”的节点。
| 条款 | 该条款后的中间结果表 | 该条款之后的图表状态,红色表示变化 | ||||||
|---|---|---|---|---|---|---|---|---|
匹配 (j:Person) 其中 j.name 以“J”开头
|
|
| ||||||
创建 (j)-[:FRIEND]->(jj:Person {name: "Jay-jay"})
|
|
|
需要注意的是,即使名称“Jay-jay”以“J”开头,该MATCH子句也无法找到Person由该子句创建的节点。这是因为该子句位于该子句之后,因此无法观察到该子句对图所做的任何更改。CREATECREATEMATCHMATCHCREATE
查询UNION
UNION查询略有不同,因为两个或多个查询的结果放在一起,但每个查询都以一个包含中间结果的空表开始。
在带有 子句的查询中UNION,之前的任何子句都无法观察到之后的子句UNION所做的写入。之后的任何子句都可以观察到之前子句所做的所有写入。 这意味着 子句永远无法观察到 之后子句所做的写入的规则在使用 的查询中仍然适用。UNION UNIONUNIONUNION
UNION
使用与上面相同的示例图,此示例显示以下查询的每个子句之后的中间结果表和图的状态:
CREATE (jj:Person {name: "Jay-jay"})
RETURN count(*) AS count
UNION
MATCH (j:Person) WHERE j.name STARTS WITH "J"
RETURN count(*) AS count
| 条款 | 该条款后的中间结果表 | 该条款之后的图表状态,红色表示变化 | ||||
|---|---|---|---|---|---|---|
创建(jj:Person {名称:“Jay-jay”})
|
|
| ||||
返回计数(*)作为计数
|
|
| ||||
匹配 (j:Person) 其中 j.name 以“J”开头
|
|
| ||||
返回计数(*)作为计数
|
|
|
需要注意的是,MATCH子句会查找Person由子句创建的节点CREATE。这是因为CREATE子句位于MATCH子句之前,因此MATCH可以观察到对图所做的任何更改CREATE。
CALL {}带有子查询的查询
子句中的子查询CALL {}针对每个传入的输入行进行评估。这意味着子查询中的写入子句可以执行多次。子查询的不同调用按传入输入行的顺序依次执行。
子查询的后续调用可以观察到子查询的早期调用所做的写入。
CALL {}
使用与上面相同的示例图,此示例显示以下查询的每个子句之后的中间结果表和图的状态:
MATCH (john:Person {name: 'John'})
SET john.friends = []
WITH john
MATCH (john)-[:FRIEND]->(friend)
WITH john, friend
CALL {
WITH john, friend
WITH *, john.friends AS friends
SET john.friends = friends + friend.name
}
| 条款 | 该条款后的中间结果表 | 该条款之后的图表状态,红色表示变化 | ||||||
|---|---|---|---|---|---|---|---|---|
匹配(约翰:人 {名称:'约翰'})
|
|
| ||||||
设置约翰.朋友=[]
|
|
| ||||||
匹配 (约翰)-[:朋友]->(朋友)
|
|
| ||||||
|
第一次调用 与 *, john.friends AS friends
|
|
| ||||||
|
第一次调用 设置约翰.朋友 = 朋友 + 朋友.姓名
|
|
| ||||||
|
第二次调用 与 *, john.friends AS friends
|
|
| ||||||
|
第二次调用 设置约翰.朋友 = 朋友 + 朋友.姓名
|
|
|
值得注意的是,在子查询中,该WITH子句的第二次调用可以观察到该子句第一次调用所做的写入SET。


被折叠的 条评论
为什么被折叠?



