对Cypher和Neo4j不熟悉,我在构建用例的查询时遇到问题。我正在构建一个简单的ACL(访问控制列表),并且正在寻找通过权限关系的路径。一张图片可以更好地解释它:
Key:
Users -> Blue
Groups -> Yellow, Green
Resource Tree -> Red
现在我想看看Bob是否存在路径到 eVar 33 资源,其中Bob有更新访问权限。因为有直接路径,我可以通过运行
获得我想要的东西MATCH p =(usr:Usr)-[:AXO {update: true}]->(aco:ACO)
WHERE usr.name = 'Bob' AND aco.name = 'eVar 33'
RETURN p
但是现在,Bob还是 Media Mgmt 组的成员,该组授予他读取对 Conversion 资源的访问权限。并且因为 Conversion 比 eVar 33 更靠资源树, eVar 33 应该继承此权限。但是,当我运行查找{read: true}
的相同查询时,找不到路径。我知道这是因为我不允许遍历:IN
和:HAS
关系,但我该怎么办呢?
我试过了:
MATCH p =(usr:Usr)-[:IN|:HAS|:AXO {read: true}]->(aco:ACO)
WHERE usr.name = 'Bob' AND aco.name = 'eVar 33'
RETURN p
认为这会允许遍历这些关系,但它仍然找不到路径(因为我不允许超过1的深度?)。
所以这是我的需求:
不,我不为耐克工作。这里只是一个示例用例:)
答案 0 :(得分:5)
这样做你想要的吗?
MATCH (bob:User { name:"Bob" })-[:IN*0..]->(group)-[:AXO { read:true }]->(res1)-[:HAS*0..]->(res2 { name:"eVar 33" })
RETURN count(*)
我认为这个问题的意思是:“给我用户Bob,以及他对资源eVar 33的任何[:AXO{read:true}]
关系。你可以通过零或更多[:IN]
来访问资源通过Bob的组,以及零个或多个[:HAS]
,因为资源继承了权限“。
>1
表示读取权限,0
表示不是。
如果您的[:IN]
或[:HAS]
树非常复杂,您可能需要限制深度。
修改强>
Wrt通过返回第一条路径进行优化评论,如何以这种方式控制查询执行并不总是显而易见的,有时你必须知道Cypher何时以及如何懒惰。将结果限制为1可能就足够了,但在这种情况下,稍微重新构造查询可能更重要,例如:“如果他与资源eVar 33有任何[:AXO{read:true}]
关系,请给我用户Bob。您可以通过。 ..“
现在从Bob到资源的路径是一个谓词,用于过滤MATCH
子句中的Bobs。在Cypher中,类似
MATCH (bob:User { name:"Bob" })
WHERE bob-[:IN*0..]->()-[:AXO { read:true }]->()-[:HAS*0..]->({ name:"eVar 33" })
RETURN true
如果路径谓词的计算结果为false,则不会返回任何内容。如果要根据返回的内容而不是返回某些内容来确定权限,请不要使用WHERE
但只返回谓词的计数,或者更好地断言谓词的计数为1。该模式不是MATCH
子句的一部分,它不会扩展您的结果,因此计数将为0或1(如果只有一个Bob)。
MATCH (bob:User { name:"Bob" })
RETURN 1 = count (bob-[:IN*0..]->()-[:AXO { read:true }]->()-[:HAS*0..]->({ name:"eVar 33" }))
它可能“感觉”像计算路径谓词意味着计算路径,但事实并非如此。尝试删除{read:true}
以获取图表中包含多个匹配项的路径模式 - 将其计算为谓词仍为1。
MATCH (bob:User { name:"Bob" })
RETURN 1 = count (bob-[:IN*0..]->()-[:AXO]->()-[:HAS*0..]->({ name:"eVar 33" }))
尝试分析此类查询,并与第一个查询进行比较LIMIT 1
,以查看哪个执行计划最有意义。
答案 1 :(得分:2)
我没有您的数据,所以我无法验证这是否有效,但是可以使用以下内容:
MATCH path1 = (usr:Usr)-[axoRel1:AXO*1..10]->(aco1:ACO)
OPTIONAL MATCH path2 = usr-[b:IN]->(group:Group)-[axoRel2:AXO*1..10]->(aco2:ACO)
WHERE usr.name = 'Bob' AND
aco1.name = 'eVar 33' AND
aco2.name = 'eVar 33' AND
filter(y in axoRel2 WHERE y.update = true) = axoRel2
filter(x in axoRel1 WHERE x.update = true) = axoRel1
RETURN path1, path2;
OPTIONAL MATCH
部分可以匹配通过"组"节点,如媒体管理,不要求用户必须属于一个组。
axoRel1:AXO*1..10
部分匹配1到10跳AXO
个关系。请注意,当您使用变量路径位时,您不再可以使用{ update: true }
语法,因为axoRel1
是关系的集合,而不是单个关系。要根据update: true
对filter
子句中WHERE
语句的含义进行过滤。当update = true的过滤关系集与实际集相同时,您知道所有这些关系都具有update = true。