Graph Neo4J/Cypher:如何过滤路径的节点?

Graph Neo4J/Cypher:如何过滤路径的节点?,graph,neo4j,cypher,Graph,Neo4j,Cypher,我想得到一个图上经过给定节点的所有简单循环/电路。通过这个密码查询,我能够做到: MATCH p=(n)-[*]->(n) WHERE n.postId = 71 //postId is a node property RETURN nodes(p) 但是,上面检索的是“回路”中的重复节点(起点和终点节点除外),根据图论,该回路根本不是回路 通过以下查询,我可以删除电路中的重复项,但我必须限制匹配模式中电路或路径的长度,这是一种硬编码模式 // In this example the l

我想得到一个图上经过给定节点的所有
简单循环
/
电路
。通过这个密码查询,我能够做到:

MATCH p=(n)-[*]->(n)
WHERE n.postId = 71 //postId is a node property
RETURN nodes(p)
但是,上面检索的是“回路”中的重复节点(起点和终点节点除外),根据图论,该回路根本不是回路

通过以下查询,我可以删除电路中的重复项,但我必须限制
匹配
模式中电路或路径的长度,这是一种硬编码模式

// In this example the length of the path is hardcoded to 4
MATCH p=
    (n)-[:RELATES_TO]->
    (p2)-[:RELATES_TO]->
    (p3)-[:RELATES_TO]->
    (p4)-[:RELATES_TO]->(n)
WHERE n.postId = 71
    AND p2.postId <> 71
    AND p3.postId <> 71
    AND p4.postId <> 71
RETURN nodes(p)
重要提示:

  • 我知道如何限制路径的长度(通过WHERE length()约束或with)

您可能需要试用APOC过程库,特别是图形算法部分中的函数。简单路径不应具有重复节点

编辑

请注意,目前该算法不能按原样用于查找开始节点和结束节点相同的简单循环


但是,如果将结束节点定义为循环中倒数第二步,即与开始节点具有定向关系的开始节点的所有相邻节点,则您应该能够获得结果(尽管路径显然不包括完成循环的开始节点的最终遍历).

尽管这可能不如使用AllSimplePath APOC过程快,正如@InverseFalcon所建议的那样(我还没有尝试过),但这里有一个方法可以在纯密码中获得简单路径:

MATCH p=(n)-[*]->(n)
WHERE n.postId = 71
WITH NODES(p) AS nds
UNWIND nds AS nd
WITH nds, COUNT(DISTINCT nd) AS dnd
WHERE dnd = LENGTH(nds)-1
RETURN nds;
基本上,此查询要求路径中的不同节点数等于节点数减去1(因为最后一个节点必须与第一个节点相同)。

是否尝试使用或?我想我正确地理解了您的问题,但以下是我如何使用上述函数。(如果此选项处于关闭状态,则只需按下即可。)

要点:

但这不是OP的问题。)


(1) 获取从一个人到一个电话号码的所有可能路径(为可读性而编辑):


(2) 使用
none()
通过筛选出包含特定节点(具有特定属性或标签的节点)的路径来删除冗余:


(3) 使用
filter()
从返回的路径中删除特定节点:

MATCH path = (p:Person)-[*]-(n:PhoneNumber)
WITH nodes(path) as ns
WHERE NONE(node IN ns WHERE (exists(node.name) and node.name ='Gorduin'))
RETURN filter(node in ns  WHERE NOT node:Person) as personless_nodelist;

╒══════════════════════════════════════════════════════════════╕
│"personless_nodelist"                                         │
╞══════════════════════════════════════════════════════════════╡
│[pn]                                                          │
├──────────────────────────────────────────────────────────────┤
│[e19,pn]                                                      │
└──────────────────────────────────────────────────────────────┘

谢谢@InverseFalcon,我来看看。不知道有这么神奇的插件存在…!:)我以这种方式执行
allSimplePaths
过程
MATCH(from:Post{postId:71}),(to:Post{postId:71})调用apoc.algo.allSimplePaths(from,to,'related_to',5)产生路径返回*
它返回一个节点,这个节点的属性
postId=71
很不幸。我明天会在上面记录一个bug。我为此创建了一个。我还更新了我的答案,加入了一个仍然使用所有SimplePath的解决方案。如果我错了,请纠正我,这似乎会计算所有允许重复的简单路径,然后删除具有重复节点的路径。这是正确的吗?在Cypher中,您不能影响可变长度关系的遍历(这是必须的,Cypher是声明性的),因此任何解决方案都必须在事实发生后进行过滤。使用Java,您可以在找到重复的路径后立即停止超出给定路径的遍历,包括与开始节点相同的结果,否则将其排除在外。
CREATE
  (g:Person {name: 'Gorduin'}), (a:Person {name: 'Alvaro'}),
  (pn:PhoneNumber {number: '555-512-2017'}),
  (e11:Extension {extension: 11}),
  (e27:Extension {extension: 27}),
  (e19:Extension {extension: 19}),

  (e11)-[:extension_of]->(pn)<-[:extension_of]-(e27),
  (e19)-[:extension_of]->(pn),

  (g)<-[:phone_number_of]-(e11),
  (g)<-[:phone_number_of]-(e27),
  (a)<-[:phone_number_of]-(e19),
  (a)<-[:phone_number_of]-(pn);
MATCH path = (p:Person)-[*1..3]-(n:PhoneNumber)
RETURN nodes(path);
MATCH path = (p:Person)-[*]-(n:PhoneNumber)
RETURN nodes(path) as every_possible_path_from_a_Person_to_a_PhoneNumber;

╒══════════════════════════════════════════════════════════════════════╕
│"every_possible_path_from_a_Person_to_a_PhoneNumber"                  │
╞══════════════════════════════════════════════════════════════════════╡
│[a,pn]                                                                │
├──────────────────────────────────────────────────────────────────────┤
│[g,e11,pn,e19,a,pn]                                                   │
├──────────────────────────────────────────────────────────────────────┤
│[g,e27,pn,e19,a,pn]                                                   │
├──────────────────────────────────────────────────────────────────────┤
│[g,e11,pn]                                                            │
├──────────────────────────────────────────────────────────────────────┤
│[a,pn,e27,g,e11,pn]                                                   │
├──────────────────────────────────────────────────────────────────────┤
│[a,e19,pn,e27,g,e11,pn]                                               │
├──────────────────────────────────────────────────────────────────────┤
│[a,e19,pn]                                                            │
├──────────────────────────────────────────────────────────────────────┤
│[g,e11,pn,a,e19,pn]                                                   │
├──────────────────────────────────────────────────────────────────────┤
│[g,e27,pn,a,e19,pn]                                                   │
├──────────────────────────────────────────────────────────────────────┤
│[g,e27,pn]                                                            │
├──────────────────────────────────────────────────────────────────────┤
│[a,pn,e11,g,e27,pn]                                                   │
├──────────────────────────────────────────────────────────────────────┤
│[a,e19,pn,e11,g,e27,pn]                                               │
└──────────────────────────────────────────────────────────────────────┘
MATCH path = (p:Person)-[*]-(n:PhoneNumber)
WITH nodes(path) as ns
WHERE NONE(node IN ns WHERE (exists(node.name) and node.name ='Gorduin'))
RETURN ns as path_nodes_NOT_containing_a_specific_person;

╒══════════════════════════════════════════════════════════════╕
│"path_nodes_NOT_containing_a_specific_person"                 │
╞══════════════════════════════════════════════════════════════╡
│[a,pn]                                                        │
├──────────────────────────────────────────────────────────────┤
│[a,e19,pn]                                                    │
└──────────────────────────────────────────────────────────────┘
MATCH path = (p:Person)-[*]-(n:PhoneNumber)
WITH nodes(path) as ns
WHERE NONE(node IN ns WHERE (exists(node.name) and node.name ='Gorduin'))
RETURN filter(node in ns  WHERE NOT node:Person) as personless_nodelist;

╒══════════════════════════════════════════════════════════════╕
│"personless_nodelist"                                         │
╞══════════════════════════════════════════════════════════════╡
│[pn]                                                          │
├──────────────────────────────────────────────────────────────┤
│[e19,pn]                                                      │
└──────────────────────────────────────────────────────────────┘