neo4j - neo4j Cypher - 检查是否存在精确图
问题描述
我使用 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
尝试获取关系计数时我错过了什么?
解决方案
编辑: 跳转到下面的最后一个 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
推荐阅读
- python - Whatsapp 聊天导出的编码是否发生了变化?
- javascript - 在 props 接收 Redux 状态之前受保护的 React 路由重定向
- macos - 我无法通过 Visual Studio for Mac 安装教程的 remotebuild 部分
- docker - 什么是 docker run -r 标志
- ios - Obj-C - 关闭所有推送的视图控制器会导致崩溃?
- javascript - 如何在另一个函数中使用地图函数和箭头函数?
- python - Selenium 找不到输入元素
- vba - 如何使打开文档时按下的功能区切换按钮在首次切换时表现正常?
- java - 在 intellij 中的模块之间使用共享 jar 时,添加模块依赖项、库和全局库有什么区别?
- javascript - 如果年份大于 4 个字符而没有 moment.js,则获取无效日期