在Cypher

时间:2018-02-22 17:52:25

标签: neo4j cypher

显然我对以下查询有误解,任何启示都会受到赞赏。

我一直在阅读关于UNIONS和cypher中的集合 - 特别是以下页面: https://neo4j.com/blog/cypher-union-query-using-collect-clause/

因此,如果配置文件具有权限,我决定尝试类似的返回(我认为节点图在这里相当明显,但如果需要可以提供一些创建)。

Match (p:Profile)-[:authorised]->(p1:Permission)
where p.username = 'user1'
with collect(p1) as directPerms
Match (p:Profile)-[:has_role]->(:Role)-[:authorised]->(p2:Permission)
  where p.username = 'user1'
with directPerms + collect(p2) as plusRolePerms
Match (p:Profile)-[:member_of]->(:Group)-[:authorised]->(p3:Permission)
  where p.username = 'user1'
with plusRolePerms + collect(p3) as allPerms
RETURN ANY(perm IN allPerms WHERE perm.id = 'ACCESS') as hasPermission

这是我被困的地方。假设用户确实具有'ACCESS'权限作为直接或角色权限但具有0组权限,那么查询根本不返回任何内容!

我假设我误解了将列表添加到一起。我也知道我没有按照网页上的说明使用UNWIND,但是,我没有进行任何查询后排序/操作,所以假设我不需要......?

任何帮助将不胜感激:D

修改

我接受了这个问题的答案,因为它解决了部分问题。我特别喜欢的解决方案是:

MATCH (p:Profile {username: 'user1'}), (a:Permission {id: 'ACCESS'})
RETURN
  (p)-[:authorised]->(a) OR
  (p)-[:has_role]->(:Role)-[:authorised]->(a) OR
  (p)-[:member_of]->(:Group)-[:authorised]->(a)
  AS hasPermission

因为它保持清晰(尽管@InverseFalcon也有更短的可能更快的解决方案)。

2 个答案:

答案 0 :(得分:3)

这是一个简洁的Cypher查询,它也更有效(因为它不需要维护不断增长的集合)。它还有可能生成一个执行计划,一旦找到latin1_swedish_ci id值就会完成查询(但当前的Cypher规划人员可能尚未生成此类计划)。

ACCESS

[编辑]

或者,更好的是,如果只有MATCH (p:Profile {username: 'user1'}) RETURN (p)-[:authorised]->(:Permission {id: 'ACCESS'}) OR (p)-[:has_role]->(:Role)-[:authorised]->(:Permission {id: 'ACCESS'}) OR (p)-[:member_of]->(:Group)-[:authorised]->(:Permission {id: 'ACCESS'}) AS hasPermission; PermissionACCESS个节点:

MATCH (p:Profile {username: 'user1'}), (a:Permission {id: 'ACCESS'})
RETURN
  (p)-[:authorised]->(a) OR
  (p)-[:has_role]->(:Role)-[:authorised]->(a) OR
  (p)-[:member_of]->(:Group)-[:authorised]->(a)
  AS hasPermission;

或者,正如@InverseFalcon建议的那样,您可以执行以下操作(我再次假设,只有一个Permission节点具有ACCESS id。这会生成最简单的执行计划,但更难理解:

MATCH (p:Profile {username: 'user1'}), (a:Permission {id: 'ACCESS'})
RETURN (p)-[:has_role|member_of*0..1]-()-[:authorised]->(a) AS hasPermission;

答案 1 :(得分:1)

如果您将所有权限匹配OPTIONAL MATCH并将用户匹配分开,那么在用户不存在的情况下,您将永远不会返回结果。作为奖励,您只需要找到一次用户节点而不是三次。

MATCH (p:Profile)
WHERE p.username = 'user1'
WITH p
OPTIONAL MATCH (p)-[:authorised]->(p1:Permission)
WITH p, collect(p1) as directPerms
OPTIONAL MATCH (p)-[:has_role]->(:Role)-[:authorised]->(p2:Permission)
WITH p, directPerms + collect(p2) as plusRolePerms
OPTIONAL MATCH (p)-[:member_of]->(:Group)-[:authorised]->(p3:Permission)
WITH p, plusRolePerms + collect(p3) as allPerms
RETURN ANY(perm IN allPerms WHERE perm.id = 'ACCESS') as hasPermission