Neo4j Cypher查询:查找属于含XYZ组且不属于含ABC组的用户
问题原因
你现有查询的问题主要有两点:
- 逻辑层面:WHERE条件仅对当前匹配到的单个Group节点做校验,没有校验该用户关联的所有Group节点,因此无法过滤掉「同时加入含XYZ组和含ABC组」的用户
- 性能层面:使用
shortestPath完全多余,User到Group通过MemberOf关联本身就是直接的一跳关系,不需要额外计算最短路径,反而会增加性能开销
正确查询写法
推荐使用NOT EXISTS子查询实现需求,逻辑清晰且性能优异:
MATCH (u:User)-[:MemberOf]->(g:Group) WHERE g.name CONTAINS 'XYZ' AND NOT EXISTS { // 校验当前用户是否有任何关联的含ABC的组 MATCH (u)-[:MemberOf]->(gBad:Group) WHERE gBad.name CONTAINS 'ABC' } RETURN DISTINCT u.name, COLLECT(DISTINCT g.name) AS xyzGroupNames
如果使用的是不支持子查询的低版本Neo4j,可以用OPTIONAL MATCH替代:
MATCH (u:User)-[:MemberOf]->(g:Group) WHERE g.name CONTAINS 'XYZ' OPTIONAL MATCH (u)-[:MemberOf]->(gBad:Group) WHERE gBad.name CONTAINS 'ABC' // 过滤掉存在关联含ABC组的用户 WITH u, g, gBad WHERE gBad IS NULL RETURN DISTINCT u.name, COLLECT(DISTINCT g.name) AS xyzGroupNames
逻辑说明
- 外层MATCH先筛选出所有至少加入过1个名称含XYZ的Group的用户
- 过滤条件排除所有存在任意关联含ABC的Group的用户
- 加
DISTINCT是避免同一用户加入多个XYZ组时出现重复的用户记录,COLLECT可以一次性返回该用户所属的所有符合条件的XYZ组名称
内容的提问来源于stack exchange,提问作者Lo Zio
相关产品推荐
相关产品推荐

