Neo4j通过属性过滤器指导路径与多个关系

时间:2014-05-28 17:14:37

标签: neo4j cypher acl

对Cypher和Neo4j不熟悉,我在构建用例的查询时遇到问题。我正在构建一个简单的ACL(访问控制列表),并且正在寻找通过权限关系的路径。一张图片可以更好地解释它:

enter image description here

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的深度?)。

所以这是我的需求:

  • 未知的路径深度
  • 我回来的任何路径都很好(我真正关心的是"是否有路径?")
  • 必须能够从用户获取资源并且当遵循AXO关系时,它必须与属性过滤器匹配。
  • 必须遵循有向图(例如,Bob没有 Analytics 的权限)

不,我不为耐克工作。这里只是一个示例用例:)

2 个答案:

答案 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: truefilter子句中WHERE语句的含义进行过滤。当update = true的过滤关系集与实际集相同时,您知道所有这些关系都具有update = true。