Cypher 查询一个组中的用户,但不在另一个组中

Cypher query for user in a group but not in another

我正在尝试创建一个看似简单的查询,但无法获得最终结果。 我在 Neo4j 中转储了我的目录。我想找到属于名称包含 XYZ 并且属于包含 [=15= 的任何组的 NOT 的组的所有用户]ABC。 这是我到目前为止创建的:

MATCH p=shortestPath((u:User)-[r:MemberOf]->(g:Group))  WHERE g.name contains 'XYZ' AND not g.name  contains 'ABC' RETURN u.name,g.name

这当然不行。第一部分没问题,组中有 XYZ 的用户,第二部分则不然。 有人可以帮我吗?谢谢 谢谢

你能试试这个方法吗:

MATCH p=shortestPath((u:User)-[r:MemberOf]->(g:Group))  
WHERE g.name contains 'XYZ' 
AND SIZE(
      [gName IN [(u)-[:MemberOf]->(g:Group) | g.name] WHERE gName CONTAINS 'ABC'])=0
RETURN u.name,g.name   

第二次尝试,按照 OP 中的要求仅返回用户。恕我直言,不需要最短路径。

WITH 'XYZ' AS includeString, 'ABC' AS excludeString
MATCH (u:User)
WHERE ANY(groupName IN [(u)-[:MemberOf]->(g:Group) | g.name] WHERE groupName CONTAINS includeString)
      AND
      NONE(groupName IN [(u)-[:MemberOf]->(g:Group) | g.name] WHERE groupName CONTAINS excludeString)
RETURN u.name

一个简单的 NOT EXISTS {} 子查询就可以解决这个问题,为此您需要 Neo4j 4.x:

MATCH p=shortestPath((u:User)-[r:MemberOf]->(g:Group))  
WHERE g.name contains 'XYZ' AND NOT EXISTS {
  MATCH (u)-[:MemberOf]->(exclude:Group)
  WHERE exclude.name CONTAINS 'ABC'
}
RETURN u.name, g.name

请注意,使用 shortestPath 查询时,会在扩展它们之间的路径之前找到两个端节点,因此您的查询将从所有以 [=15= 开头的 :Group 节点的叉积中生成许多行],以及所有不属于 'ABC' 组的 :User 节点,那么它将从该叉积结果中寻找所有行之间的最短路径。这听起来效率不高,因此您可能需要重新考虑您的 shortestPath() 方法。

感谢上面的两位用户,我混合了查询并得到了结果:

WITH 'incl-regex' AS includeString, 'excl-regex' AS excludeString
MATCH p=(u:User)-[r:MemberOf]->(g:Group)  
WHERE toupper(g.name) =~ includeString AND NOT EXISTS {
  MATCH (u)-[:MemberOf]->(exclude:Group)
  WHERE toupper(exclude.name) =~ excludeString
}
RETURN u.name, g.name

这既快速(没有最短路径)又准确。我发现 @InverseFalcon 版本更容易理解,因为它读起来就像我想实现“给我这样的用户而不是那样的组”。 我需要一些正则表达式调整,因为组名称非常复杂。