Cypher 查询中的多个 MATCH 子句和逗号有啥区别?

Posted

技术标签:

【中文标题】Cypher 查询中的多个 MATCH 子句和逗号有啥区别?【英文标题】:What is the difference between multiple MATCH clauses and a comma in a Cypher query?Cypher 查询中的多个 MATCH 子句和逗号有什么区别? 【发布时间】:2015-09-23 14:47:38 【问题描述】:

在 Neo4j 的 Cypher 查询语言中,一个 MATCH 子句紧跟另一个如下有什么区别:

MATCH (d:Documentdocument_ID:2)
MATCH (d)--(s:Sentence)
RETURN d,s

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

MATCH (d:Documentdocument_ID:2),(d)--(s:Sentence)
RETURN d,s

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

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

【参考方案2】:

我认为最好在有差异时提供一个示例来进行解释。 假设我们有官方 Neo4j 教程提供的“Movie”数据库。 :Person:Movie 节点之间总共有 10 个 :WROTE 关系

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 = p2m = m2 具有相同关系(:WROTE)的记录被排除

比如第一种情况下有一条记录(两个MATCH子句)

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

“亚伦·索尔金”“几个好男人”“亚伦·索尔金”“几个好男人”

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

【讨论】:

【参考方案3】:

这些条款之间没有区别只要条款不相互链接

如果你这样做了:

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

同理:

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

因为(也只是因为)ab 是独立的。如果ab 通过关系链接,那么查询的含义可能会改变。

【讨论】:

【参考方案4】:

以更通用的方式,“不能在同一结果记录中多次返回同一关系。”[参见1.5. Cypher Result Uniqueness in the Cypher manual]

MATCH-after-MATCH 和带有逗号分隔模式的单个 MATCH 都应在逻辑上返回笛卡尔积。除了逗号分隔的模式,我们必须排除那些我们已经添加了关系的记录。

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

【讨论】:

【参考方案5】:

如果查询的一部分包含多个不连贯的模式,这将在所有这些部分之间构建一个笛卡尔积。这可能会产生大量数据并减慢查询处理速度。虽然偶尔是有意的,但通常可以通过在不同部分之间添加关系或使用 OPTIONAL MATCH (identifier is: (a)) 来重新制定避免使用此叉积的查询。 简而言之,它们在这两个查询中没有区别,但非常小心地使用它。

【讨论】:

【参考方案6】:

以更通用的方式,“在同一结果记录中,不能多次返回同一关系。” [见 1.5。 Cypher 手册中的 Cypher 结果唯一性]

这个说法怎么样?

MATCH p1=(v:player)-[e1]->(n) 
MATCH p2=(n:team)<-[e2]-(m) 
 WHERE e1=e2 
RETURN e1,e2,p1,p2

【讨论】:

以上是关于Cypher 查询中的多个 MATCH 子句和逗号有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Cypher 中的变量需要提醒 `WITH` 子句?

Cypher:使用 WHERE 子句或 MATCH 属性定义进行精确匹配?

Cypher where子句因多条路径而失败

Cypher基本指令学习1

带有两个 OPTIONAL MATCH 和两个单独的 WITH 语句的 Cypher 查询

使用cypher返回多个关系权重