首页 文章

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

提问于
浏览
1

我希望在通过给定节点的图形上获得所有 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

    虽然这可能没有使用allInmpleFscon所建议的那样使用allSimplePaths APOC过程那么快(我还没有尝试过),但是这里有一个在纯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;
    

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

  • 0

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

    编辑

    注意,当前该算法当前不能用于查找起始节点和结束节点相同的简单循环 .

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

  • 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节点(路径);
    但这不是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]                                                      │
    └──────────────────────────────────────────────────────────────┘
    

相关问题