Neo4j OPTIONAL MATCH不返回null

时间:2017-02-04 18:52:34

标签: neo4j

在Neo4j中,图中有4个人节点; 2与电影节点有关系,其他2没有关系。

期望下面的查询只返回2个没有关系的节点,但它返回all。

如果查询中遗漏了任何内容,请告诉我。我是Neo4J的新手

MATCH (p:Person) 
OPTIONAL MATCH (p) -[r]- (m:Movie)  
Where type(r) = null 
Return p,type(r),m

谢谢!

1 个答案:

答案 0 :(得分:1)

您获得意外结果的原因是由于WHERE子句的位置和含义,以及它与OPTIONAL MATCH行为的相互作用。

WHERE仅适用于前面的MATCH,OPTIONAL MATCH或WITH。在这种情况下,它不适用于查询的所有结果,它仅适用于OPTIONAL MATCH,并且这与您期望的行为完全不同。

如果您将其隔离并查看OPTIONAL MATCH和WHERE,它会有所帮助:

OPTIONAL MATCH (p) -[r]- (m:Movie)  
Where type(r) = null 

这意味着:可选地从p匹配到:电影m到关系r,其中r为空。你不能拥有一个存在的关系,但它的类型是null,这是不可能的,所以这个可选的MATCH总会失败。

但是因为它是一个可选的MATCH,所以不会删除行,而是非匹配的元素将为null。结果是行:Person p(来自您之前的匹配),null为类型(r)和m。

您实际想要的是首先执行可选匹配,然后过滤掉类型为null的行。你想要一个影响查询所有行的WHERE,而不是OPTIONAL MATCH。

这要求我们添加一个WITH子句,并在其后移动WHERE:

MATCH (p:Person) 
OPTIONAL MATCH (p) -[r]- (m:Movie)  
WITH p, r, m
Where type(r) = null 
Return p, type(r), m

将WHERE从OPTIONAL MATCH移动到WITH更改其含义,它现在将应用于查询的所有行,并且因为它不再与可选MATCH相关联,它实际上会删除不适合的行谓词,而不是保持行和设置元素为空。

现在,所有这一切,有一个更容易的查询返回你想要的东西而不使用OPTIONAL MATCH:

MATCH (p:Person) 
WHERE NOT (p)--(:Movie) 
RETURN p

匹配:与那些没有关系的人员节点:人员到:电影节点。

我们可以省略返回关系类型和电影节点,因为那些根据你的匹配不存在。