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

时间:2016-08-31 20:32:16

标签: graph neo4j cypher

我希望在通过给定节点的图表上获取所有simple cycles / circuits。我能够使用这个密码查询:

MATCH p=(n)-[*]->(n)
WHERE n.postId = 71 //postId is a node property
RETURN nodes(p)

但是,上面检索了“电路”中的重复节点。 (根据图论,根据开始和结束节点除外),根本不是电路。

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

// 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)

有没有办法在第一个查询中过滤关系之间的节点?

MATCH p=(n)-[*]->(n)
WHERE n.postId = 71 //postId is a node property
RETURN nodes(p)

重要说明:

3 个答案:

答案 0 :(得分:0)

您可能想要试用APOC程序库,特别是图算法部分中的allSimplePaths函数。简单路径应该没有重复节点。

修改

请注意,目前该算法目前无法用于查找起始节点和结束节点相同的简单循环。

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

答案 1 :(得分:0)

虽然这可能没有使用allSimplePaths APOC程序那么快,正如@InverseFalcon所建议的那样(我还没有尝试过),这里有一个在纯Cypher中获取简单路径的地方:

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;

基本上,此查询要求路径中 distinct 节点的数量等于节点数减1(因为最后一个节点必须与第一个节点相同)。

答案 2 :(得分:0)

您是否尝试过使用filter()none()?我想我正确地理解了你的问题,但这就是我如何使用上述功能。 (如果这是关闭的,只需要帮助。)

要点:http://console.neo4j.org/?id=99xkcu

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);

enter image description here

需要使用可变长度查询,因为:phone_number_of指针可以来自扩展名(链接到电话号码)或电话号码本身。箭头方向无关紧要,您可以撤消其中任何一个并尝试以下查询。

  

(限制查询的长度将是我的明显解决方案   例如

MATCH path = (p:Person)-[*1..3]-(n:PhoneNumber)
RETURN nodes(path);
     

但这不是OP的问题。)

(1)获取从人到电话号码的每条可能路径(为便于阅读而编辑):

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]                                               │
└──────────────────────────────────────────────────────────────────────┘

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

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]                                                    │
└──────────────────────────────────────────────────────────────┘

(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]                                                      │
└──────────────────────────────────────────────────────────────┘