多个MATCH子句和逗号在Cypher查询中有什么区别?

53

在Neo4j的Cypher查询语言中,一个MATCH子句紧接着另一个MATCH子句的写法有何不同:

MATCH (d:Document{document_ID:2})
MATCH (d)--(s:Sentence)
RETURN d,s

与同一MATCH子句中的逗号分隔模式相比怎么样?例如:

MATCH (d:Document{document_ID:2}),(d)--(s:Sentence)
RETURN d,s

在这个简单的例子中,结果是相同的。但是是否存在任何“陷阱”?

6个回答

33

有一个区别:逗号分隔的匹配实际上被视为同一模式的一部分。因此,保证每个关系在生成的路径中只出现一次。

独立的 MATCH是不同的操作,它们的路径不能形成单一的模式,并且没有这些保证。


11

我认为举例说明会更好一些,这样可以更清晰地展示差异。 比如我们有一个"电影"数据库,它是由Neo4j官方教程提供的。 总共有10个:WROTE关系,连接了:Person:Movie节点。

MATCH (:Person)-[r:WROTE]->(:Movie) RETURN count(r); // returns 10

1) 让我们尝试使用两个MATCH子句来执行下一个查询:

MATCH (p:Person)-[:WROTE]->(m:Movie) MATCH (p2:Person)-[:WROTE]->(m2:Movie)
RETURN p.name, m.title, p2.name, m2.title;

当然您将在结果中看到10*10 = 100条记录。

2)让我们尝试一个带有一个MATCH子句和两个模式的查询:

MATCH (p:Person)-[:WROTE]->(m:Movie), (p2:Person)-[:WROTE]->(m2:Movie) 
RETURN p.name, m.title, p2.name, m2.title;

现在你会看到返回了90 条记录。 这是因为在这种情况下,当p = p2并且m = m2且它们之间的关系 (:WROTE) 相同时,这些记录将被排除

例如,在第一种情况(两个MATCH子句)中有一条记录:

p.name m.title p2.name m2.title

"Aaron Sorkin" "A Few Good Men" "Aaron Sorkin" "A Few Good Men"

而在第二种情况(一个MATCH,两个模式)中则没有这样的记录:


6
这些内容没有区别只要这些从句彼此之间没有链接。如果你这样做:
MATCH (a:Thing), (b:Thing) RETURN a, b;

这与以下内容相同:

MATCH (a:Thing) MATCH (b:Thing) RETURN a, b;

因为(仅因为)ab是独立的。如果ab之间存在关联,那么查询的含义可能会发生改变。


5
在更通用的情况下,“同一关系不能在同一结果记录中返回多次。”[参见1.5.Cypher手册中的Cypher结果唯一性]
无论是MATCH-after-MATCH还是单个逗号分隔模式的MATCH,都应该逻辑上返回笛卡尔积。但是,对于逗号分隔模式,我们必须排除那些已经添加了关系的记录。
在安迪的答案中,这就是为什么我们在第二种情况中排除了相同电影的重复:因为每个单个MATCH的第二个表达式都在使用与第一个表达式相同的:WROTE关系。

0
以更通用的方式,“在同一结果记录中不能返回超过一次相同的关系。”[请参阅Cypher手册中的1.5.Cypher Result Uniqueness] 这个语句怎么样?
MATCH p1=(v:player)-[e1]->(n) 
MATCH p2=(n:team)<-[e2]-(m) 
 WHERE e1=e2 
RETURN e1,e2,p1,p2

0
如果查询的一部分包含多个不相关的模式,则会在所有这些部分之间建立笛卡尔积。这可能会产生大量数据并减慢查询处理速度。虽然有时是有意为之,但通常可以重新构造查询以避免使用此交叉产品,例如通过在不同部分之间添加关系或使用OPTIONAL MATCH(标识符为:(a))。 简而言之,这两个查询没有区别,但需要非常小心地使用它们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接