【问题标题】:neo4j Cypher - Check if exact graph existsneo4j Cypher - 检查是否存在精确图
【发布时间】:2020-09-10 22:44:36
【问题描述】:

我使用 neo4j 来表示我系统中的独特流程。
我得到以 JSON 表示的数据,在将其写入 neo4j 之前,我需要确保它尚不存在。
我们可以假设 2 个节点之间只有一种关系,并且只有 1 个入口点和 1-way 关系。

要检查图表是否存在,我需要匹配节点、关系和关系计数
我目前正在为计数而苦苦挣扎(没有它,我只检查是否包含图表)。
以下是生成的查询不起作用的示例(返回空结果):

MATCH
(n:User {userId: 1234}),
(n_0:User {userId: 3345}),
(n_1:Group {groupId: 8765}),
(n_1_0:Event {eventId:3456})

OPTIONAL MATCH
(n)-->(n_rel),
(n_0)-->(n_0_rel),
(n_1)-->(n_1_rel),
(n_1_0)-->(n_1_0_rel)

WITH
n, count(n_rel) AS n_count,
n_0, count(n_0_rel) AS n_0_count,
n_1, count(n_1_rel) AS n_1_count,
n_1_0, count(n_1_0_rel) AS n_1_0_count

WHERE (n)-[:PING {someProp:true}]->(n_0)
AND   (n)-[:JOIN {someProp:"cool"}]->(n_1)
AND   (n_1)-[:PUBLISH {otherProp: "Hello"}]->(n_1_0)
AND   n_count = 2
AND   n_0_count = 0
AND   n_1_count = 1
AND   n_1_0_count = 0

RETURN n

这是一个没有计数检查的工作

MATCH
(n:User {userId: 1234}),
(n_0:User {userId: 3345}),
(n_1:Group {groupId: 8765}),
(n_1_0:Event {eventId:3456})

WHERE (n)-[:PING {someProp:true}]->(n_0)
AND   (n)-[:JOIN {someProp:"cool"}]->(n_1)
AND   (n_1)-[:PUBLISH {otherProp: "Hello"}]->(n_1_0)

RETURN n

我在尝试获取关系计数时遗漏了什么?

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    编辑: 跳到下面的最后一个 Cypher 语句以获得最终答案。否则,请随意阅读发现的传奇

    我认为问题在于,在第一个查询中,整个 WHERE 子句仅适用于 WITH。在下面的 Cypher 中,我将第一个查询中的 WHERE 子句分成两个 WHERE,一个用于 MATCH,一个用于 WITH。希望这会产生预期的结果。

    MATCH
    (n:User {userId: 1234}),
    (n_0:User {userId: 3345}),
    (n_1:Group {groupId: 8765}),
    (n_1_0:Event {eventId:3456})
    
    WHERE (n)-[:PING {someProp:true}]->(n_0)
    AND   (n)-[:JOIN {someProp:"cool"}]->(n_1)
    AND   (n_1)-[:PUBLISH {otherProp: "Hello"}]->(n_1_0)
    
    WITH n, n_0, n_1, n_1_0
    
    OPTIONAL MATCH
    (n)-->(n_rel),
    (n_0)-->(n_0_rel),
    (n_1)-->(n_1_rel),
    (n_1_0)-->(n_1_0_rel)
    
    WITH
    n, count(n_rel) AS n_count,
    n_0, count(n_0_rel) AS n_0_count,
    n_1, count(n_1_rel) AS n_1_count,
    n_1_0, count(n_1_0_rel) AS n_1_0_count
    
    WHERE
    n_count = 2
    AND   n_0_count = 0
    AND   n_1_count = 1
    AND   n_1_0_count = 0
    
    RETURN n
    

    使用电影图表我想出了这个查询。我相信它大致相当于您的查询,并遵循我最初建议的相同模式。它与您发现的问题相同。当 OPTIONAL MATCH 没有找到任何结果时,则不返回任何内容。

    MATCH
      (jamest:Person {name: "James Thompson"}),
      (jessicat:Person {name: "Jessica Thompson"})
    WHERE 
      (jamest)-[:FOLLOWS]->(jessicat)
    
    WITH jamest, jessicat
    
    OPTIONAL MATCH
      (jamest)-[:REVIEWED]->(jamest_rev_rel), // James Thompson has 2 REVIEWED relationships
      (jessicat)-[:FOLLOWS]->(jessicat_fol_rel) // Jessica Thompson has no outbound FOLLOWS relationships
    WITH
      jamest, count(jamest_rev_rel) AS jamest_rev_rel_count,
      jessicat, count(jessicat_fol_rel) AS jessicat_fol_rel_count
    WHERE
      jamest_rev_rel_count = 2
      AND jessicat_fol_rel_count = 0
    
    RETURN jamest, jessicat // No results returned
    

    我将查询改写成这个。这个返回预期的结果。感觉太麻烦了,但希望它能给你一些工作。我会继续修改它。

    MATCH
      (jamest:Person {name: "James Thompson"}),
      (jessicat:Person {name: "Jessica Thompson"})
    WHERE 
      (jamest)-[:FOLLOWS]->(jessicat)
    
    WITH jamest, jessicat
    
    OPTIONAL MATCH
      (jamest)-[:REVIEWED]->(jamest_rev_rel) 
    WITH
      jessicat, jamest, count(jamest_rev_rel) as jamest_rev_rel_count
    WHERE 
      jamest_rev_rel_count = 2 // James Thompson has 2 REVIEWED relationships
    
    WITH jamest, jessicat
    
    OPTIONAL MATCH
      (jessicat)-[:FOLLOWS]->(jessicat_fol_rel) 
    WITH
      jamest, jessicat, count(jessicat_fol_rel) AS jessicat_fol_rel_count
    WHERE 
      jessicat_fol_rel_count = 0 // Jessica Thompson has no outbound FOLLOWS relationships
    
    RETURN jamest, jessicat // The two nodes are returned as expected
    

    问题的根源在于一个 OPTIONAL MATCH 具有多个逗号分隔的模式,而不是多个 OPTIONAL MATCH 语句。在前者中,所有单独的模式都被认为是一个单一的模式。而在后者中,它们是不同的,这正是该查询所需要的。这个SO question 提供了更多细节。

    查询可以稍微倾斜一点。这个版本给出了与上面相同的结果,并且在我看来更具可读性

    MATCH
      (jamest:Person {name: "James Thompson"}),
      (jessicat:Person {name: "Jessica Thompson"})
    OPTIONAL MATCH 
      (jamest)-[:REVIEWED]->(jamest_rev_rel)
    OPTIONAL MATCH 
      (jessicat)-[:FOLLOWS]->(jessicat_fol_rel) 
    WITH
      jessicat, jamest, 
      count(jamest_rev_rel) as jamest_rev_rel_count, 
      count(jessicat_fol_rel) as jessicat_fol_rel_count
    WHERE 
      jamest_rev_rel_count = 2 // James Thompson has 2 outbount REVIEWED relationships 
      AND jessicat_fol_rel_count = 0 // Jessica Thompson has 0 outbound FOLLOWS relationships
    
    RETURN 
      jamest, jessicat // The two nodes are returned as expected
    

    【讨论】:

    • 感谢您的回复。这仍然不起作用,我发现了 2 个问题: 1. 在可选匹配中,与 0 个关系节点的匹配(如 (n_0)-->(n_0_rel) 使整个匹配因没有关系而失败。2 . 当删除“有问题”的那些时,n_1_count 返回 2 而不是 1,奇怪..
    • 我玩弄了电影图表,并能够根据我的原始建议重新创建您发现的问题。请检查我在回复中添加的密码,看看是否有帮助。
    • 我明白了,我必须为每个计数将可选匹配分解为不同的语句。谢谢!会接受你的回答。如果你能想出更“干净”的东西,请 LMK。
    • 查询需要多个 OPTIONAL MATCH 语句,但它们可以与单个 WHERE 子句组合使用。我在答案中添加了更精简的查询形式
    猜你喜欢
    • 1970-01-01
    • 2018-06-23
    • 2015-01-29
    • 1970-01-01
    • 2020-11-09
    • 1970-01-01
    • 2017-05-12
    • 2021-01-30
    • 2015-11-01
    相关资源
    最近更新 更多