【问题标题】:Neo4j OPTIONAL MATCH not returning nullNeo4j 可选匹配不返回 null
【发布时间】:2017-02-04 18:52:34
【问题描述】:

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

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

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

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

谢谢!

【问题讨论】:

    标签: neo4j


    【解决方案1】:

    您得到意外结果的原因是 WHERE 子句的位置和含义,以及它与 OPTIONAL MATCH 行为的交互。

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

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

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

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

    但是因为它是一个 OPTIONAL MATCH,所以不会删除行,而是不匹配的元素将为 null。结果是带有 :Person p 的行(来自您之前的匹配),并且 type(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 改变了它的含义,它现在将应用于查询的所有行,并且由于它不再与 OPTIONAL MATCH 关联,它实际上会删除不适合的行谓词而不是保留行并将元素设置为空。

    现在,说了这么多,有一个更简单的查询来返回你想要的,根本不使用 OPTIONAL MATCH:

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

    匹配 :Person 节点,从这些 :Persons 到 :Movie 节点没有关系。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多