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 版本更容易理解,因为它读起来就像我想实现“给我这样的用户而不是那样的组”。
我需要一些正则表达式调整,因为组名称非常复杂。
我正在尝试创建一个看似简单的查询,但无法获得最终结果。 我在 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 版本更容易理解,因为它读起来就像我想实现“给我这样的用户而不是那样的组”。 我需要一些正则表达式调整,因为组名称非常复杂。