neo4j Cypher-检查是否存在精确的图形

neo4j Cypher-检查是否存在精确的图形,neo4j,cypher,Neo4j,Cypher,我使用neo4j表示系统中的唯一流。 我用JSON表示数据,在将其写入neo4j之前,我需要确保它还不存在。 我们可以假设两个节点之间只有一个关系,并且只有一个入口点和一个方向关系 要检查图形是否存在,我需要匹配节点、关系和关系计数 我目前正在努力计数(如果没有计数,我只检查是否包含图形)。 下面是一个生成的查询不起作用的示例(返回空结果): 这里有一个正在工作的没有计数检查: MATCH (n:User {userId: 1234}), (n_0:User {userId: 3345}), (

我使用neo4j表示系统中的唯一流。
我用JSON表示数据,在将其写入neo4j之前,我需要确保它还不存在。
我们可以假设两个节点之间只有一个关系,并且只有一个入口点和一个方向关系

要检查图形是否存在,我需要匹配节点、关系和关系计数
我目前正在努力计数(如果没有计数,我只检查是否包含图形)。
下面是一个生成的查询不起作用的示例(返回空结果):

这里有一个正在工作的没有计数检查:

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
在尝试获取关系计数时,我遗漏了什么?

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

我认为问题在于,在第一个查询中,整个WHERE子句只应用于WITH。在下面的密码中,我将第一个查询中的WHERE子句分为两个WHERE,一个用于匹配,另一个用于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
使用电影图,我提出了这个查询。我相信这大致相当于您的查询,并且遵循我最初建议的相同模式。它与您发现的问题相同。当可选匹配未找到任何结果时,将不返回任何结果

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
问题的根源在于,一个可选匹配与多个逗号分隔的模式,而不是多个可选匹配语句。在前者中,所有单独的模式都被视为单个模式。而在后者中,它们是不同的,这正是这个查询所需要的。这提供了更多的细节

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

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

谢谢你的回复。这仍然不起作用,我发现了两个问题:1。在可选匹配中,与0个关系节点的匹配(如(n_0)-->(n_0_rel)中的匹配)会由于没有关系而导致整个匹配失败。2.删除“有问题”时一个,n_1_count返回为2,而不是1,奇怪..我玩了电影图表,能够重现您在我的原始建议中发现的问题。请检查我添加到我的回复中的密码,看看是否有帮助。我明白了,我必须为每个计数将可选匹配分为不同的语句。谢谢!接受您的建议吗回答。如果你能想到更“干净”的问题,请回答。查询需要多个可选的匹配语句,但它们可以组合并与单个WHERE子句一起使用。我在回答中添加了一个更精简的查询形式
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