在Graph Academy中,我们有练习4,第5部分,涉及以下问题: 2。检索电影及其演员,其中一位演员也曾执导该电影,并返回演员姓名,导演姓名和电影标题。
我尝试过:
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)<-[:DIRECTED]-(d:Person)
WHERE exists((d)-[:ACTED_IN]->(m))
RETURN p.name, d.name, m.title
结果似乎还可以,除了重复的信息。 My Result
结果显示后,我看到了图学院的预期查询,并且它做了一些小的更改,将DIRECTED更改为ACTED:IN,并使用DIRECTED更改了存在的内容,如下所示:
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)<-[:ACTED_IN]-(d:Person)
WHERE exists((d)-[:DIRECTED]->(m))
RETURN p.name, d.name, m.title
该结果: Correct result
我们看到没有重复的信息,例如演员“汤姆·汉克斯”,导演“汤姆·汉克斯”。
我的问题是,为什么Neo4j这么小的变化就表现得如此?
答案 0 :(得分:3)
这与遍历单个模式匹配时的某些唯一行为有关。
Cypher使用称为RELATIONSHIP_PATH的唯一性,这意味着对于每个路径,关系必须是唯一的-每个路径只能遍历一次。
这样做有多种原因,最值得注意的是,它隐式地防止了可变长度遍历的无限循环,因为无限循环要求您能够一遍又一遍地遍历相同的关系。
在第一个查询中,匹配项是:
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)<-[:DIRECTED]-(d:Person)
在这种情况下,同一个p
节点可能与同一个m
电影节点具有:ACTED_IN和:DIRECTED关系。这两个关系都将遍历一次,没有问题,因此p
和d
可以是同一节点,因此您会看到p
和{{ 1}},如结果所示。
在第二个查询中,匹配项是:
d
在电影图中,对于在电影中表演过的演员,在这对节点之间只有一个:ACTED_IN关系,从不超过1。
因此,MATCH (p:Person)-[:ACTED_IN]->(m:Movie)<-[:ACTED_IN]-(d:Person)
与d
不可能是同一节点。 :ACTED_IN关系将从人员节点遍历到电影节点,并且不能再次使用以从电影节点遍历到人员节点。
请注意,此限制仅对整个MATCH或OPTIONAL MATCH有效。如果您将单个MATCH分成多个,例如:
p
然后,您将在结果中看到条目,其中MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
MATCH (m)<-[:ACTED_IN]-(d:Person)
...
与p
是同一节点。由于这里有两个MATCH模式,因此对模式之间遍历的关系没有任何限制。