Neo4j 在密码查询中,多个匹配子句和逗号之间有什么区别?

Neo4j 在密码查询中,多个匹配子句和逗号之间有什么区别?,neo4j,cypher,Neo4j,Cypher,在Neo4j的Cypher查询语言中,紧跟在另一个匹配子句之后的一个匹配子句之间有什么区别,如下所示: 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 在这个简单的例子中,结果是相同的。但是有什么“陷阱”吗?如果这些子句之间没有链

在Neo4j的Cypher查询语言中,紧跟在另一个匹配子句之后的一个匹配子句之间有什么区别,如下所示:

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

在这个简单的例子中,结果是相同的。但是有什么“陷阱”吗?

如果这些子句之间没有链接,它们之间就没有区别

如果您这样做:

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

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

因为(并且仅仅因为)
a
b
是独立的。如果
a
b
通过关系链接,则查询的含义可能会改变。

有一个区别:逗号分隔的匹配实际上被视为同一模式的一部分。例如,保证每个关系在结果路径中只出现一次,这一点在这里得到了支持


单独匹配是单独的操作,其路径不形成单个模式,并且没有这些保证。

如果查询的一部分包含多个断开连接的模式,这将在所有这些部分之间构建笛卡尔积。这可能会产生大量数据并减慢查询处理速度。虽然偶尔有意这样做,但通常可以通过添加不同部分之间的关系或使用可选匹配(标识符为:(a))来重新格式化查询,以避免使用此交叉积。
简而言之,他们在这两个查询中没有区别,但使用时非常小心。

我认为最好在有区别时提供一个例子来解释。 假设我们有官方Neo4j教程提供的“电影”数据库。 在:Person和:Movie节点之间总共有10个:编写的关系

1) 让我们使用两个匹配子句尝试下一个查询:

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之间具有相同关系(:writed)的记录被排除在外

例如,第一种情况下有一条记录(两个匹配子句)

p、 名称m.title p2.name m2.title

“Aaron Sorkin”“几个好人”“Aaron Sorkin”“几个好人”

虽然在第二种情况下(一个匹配,两个模式)没有这样的记录,

以更一般的方式,“同一关系不能在同一结果记录中多次返回。”[请参阅

一个接一个的匹配以及使用逗号分隔模式的单个匹配在逻辑上都应返回笛卡尔积。除了逗号分隔模式外,我们必须排除那些已经添加了关系的记录

在安迪的回答中,这就是为什么我们在第二种情况下排除了同一部电影的重复:因为每一场比赛的第二个表达式都使用了与第一个表达式相同的:write关系

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