我正在用neo4j制作一个概念验证访问控制系统,我需要一些关于Cypher的帮助。
数据模型如下:
(:User|Business)-[:can]->(:Permission)<-[:allows]-(:Business)
现在我想获得一条从用户或业务到所有业务节点的路径,您可以通过到达这些节点
-[:can]->(:Permission)<-[:allows]-
模式。我成功地写了一篇MATCH,让我走到了一半:
MATCH
path =
(:User {userId: 'e96cca53-475c-4534-9fe1-06671909fa93'})-[:can|allows*]-(b:Business)
但这没有任何方向,我不知道如何在不将返回的匹配减少为仅直接匹配的情况下包括方向(即在:Business
节点上第一次命中后不会继续(
所以我想知道的是:
- 有没有办法在一个查询中匹配多个这样的跃点
- 我应该完全不同地建模吗
- 我是不是完全走错了路,查询应该完全重写
当前可变长度展开的语法不允许对某些类型的单独方向进行精细控制。围绕这一点,我们正在进行改进,但目前仅靠Cypher无法满足您的需求。
我们可以使用APOC程序来实现这一点,因为路径扩展程序支持对扩展中类型的方向和关系序列的精细控制。
不过,首先,您需要弄清楚如何处理用户或业务匹配,方法是向这些节点添加一个公共标签,通过该标签您可以按属性类型进行匹配,或者您可以将子查询与两个UNIONed查询一起使用,一个用于:业务节点,另一个用于用户节点,这样您仍然可以利用其中任何一个的索引,并在单个变量中获得可能的结果。
一旦你得到了,你就可以使用apoc.path.expandConfig()
,传递一些选项来获得你想要的:
// assume you've matched to your `start` node already
CALL apoc.path.expandConfig(start, {relationshipFilter:'can>|<allows', labelFilter:'>Business'}) YIELD path
RETURN path
这个不使用序列,但它确实限制了每个关系类型的扩展方向。我们还将labelFilter设置为:业务节点是路径的结束节点,而不是任何其他标签的节点。
您可以指定如下路径:
MATCH path = (:User {userId: $id})-[:can]->(:Permission)
<-[:allows]-(:Business))
RETURN path
这应该会返回您想要的结果。
我看到通过路径扩展APOC程序提供了一个很好的解决方案
但我将重点谈谈你的第二点:"><我应该完全不同地建模吗>";嗯,不完全是,但我认为是的。我应该完全不同地建模吗>
使用Neo4j真正解放的部分是,你可以像改变驾驶策略一样轻松地改变你行驶的道路:模型与查询。由于您处于项目的早期阶段,您可以尝试不同的模型。这是一个很好的机会,让只是进行语义更改,以围绕问题进行"最终运行"。
Neo4j中关系的语义通过表示
- 分配给关系的强制TYPE,与
- 选择指向强制箭头的方向
使用APOC解决的技巧是如何遍历一条关系路径,该路径沿着查询的路径在向前和向后之间交替。但是,在使用电动工具之前,为什么不改变你的任何一种关系类型的方向呢。您可以从更改允许的型号
<-[:allows]-
至
-[:is_allowed_by]->
这会给你带来很多好处。现在,两个关系的方向是相同的,您可以在匹配模式中将两个关系组合为一个关系。路径遍历可以这样表示,short&甜蜜:
(u:User)-[:can|is_allowed_by*]->(c:Company)
这将竭尽全力找到每个用户到公司的路径,包括分支。