我在Neo4j中具有以下测试数据:
merge (n1:device {name:"n1"})-[:phys {name:"phys"}]->(:interface {name:"n1a"})-[:cable {name:"cable"}]->(:interface {name:"n2a"})-[:phys {name:"phys"}]->(n2:device {name:"n2"})
merge (n1)-[:phys {name:"phys"}]->(:interface {name:"n1b"})-[:cable {name:"cable"}]->(:interface {name:"n2b"})-[:phys {name:"phys"}]->(n2)
merge (n1)-[:phys {name:"phys"}]->(:interface {name:"n1c"})-[:cable {name:"cable"}]->(:interface {name:"n2c"})-[:phys {name:"phys"}]->(n2)
merge (n1)-[:phys {name:"phys"}]->(:interface {name:"n1d"})-[:cable {name:"cable"}]->(:interface {name:"n2d"})
给予:
尽管此示例在n1和n2之间的4条路径中的每条路径上都具有3个关系和2个节点,但是我的真实数据可能具有更多的路径,也有更多的路径。
这是一个无向图,在实际数据集中,每个路径的各个部分之间的关系是双向的。
我知道每个路径都以:device开始,或者只是以非:device结束,或者是以:device结束,并且一路上可能有任意数量的关系和其他非:device节点。
所以我想做:
match p=(:device {name:"n1"})-[*]-(:device) return (p)
并使其返回相同的记录数(我很乐意加倍),记录数为:
match p=(:device {name:"n1"})-[*]->(:device) return (p)
因此,我正在寻找一种方法来停止匹配关系并在路径中遇到第一个(:device)时停止遵循该路径。
据我有限的理解,我可以通过使每个关系都是双向的来轻松实现这一目标。但是,到目前为止,我已避免使用该选项,因为我已读到它是不好的做法。
额外给专家:-)
另外,我想一种返回不以:device结尾的完整路径的方法(例如,底部的路径)
谢谢
答案 0 :(得分:2)
这是一个用例,仅使用Cypher有点困难,因为我们没有办法指定“遵循可变长度路径并在到达此类型的另一个节点时停止”。
当我们使用LIMIT时,我们可以做这样的事情,但是当我们不知道会有多少结果,或者我们需要对多个起始节点执行此操作时,这种限制就变得太严格了。
因此,有些APOC path finder procedures包含更灵活的选项。其中之一是labelFilter选项,该选项可让您描述如何过滤具有在扩展过程中找到的特定标签(黑名单,白名单等)的节点。这些过滤器之一称为termination filter(在适当的标签前使用/
符号),这意味着将结果包括到该节点的路径,并停止扩展,这正是您所要做的。正在寻找。
安装APOC之后,可以从起始节点开始使用apoc.path.expandConfig()
过程,并提供labelFilter config参数来获得以下行为:
MATCH (start:device {name:"n1"})
CALL apoc.path.expandConfig(start, {labelFilter:'/device'}) YIELD path
RETURN path