首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Neo4J/Cypher:如何过滤路径的节点?

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

Stack Overflow用户
提问于 2016-08-31 20:32:16
回答 3查看 3.2K关注 0票数 2

我希望在经过给定节点的图上获得所有的simple cycles/circuits。通过这个密码查询,我可以这样做:

代码语言:javascript
复制
MATCH p=(n)-[*]->(n)
WHERE n.postId = 71 //postId is a node property
RETURN nodes(p)

然而,根据图论,上述检索电路中的重复节点(从开始和结束节点除外)根本不是一个电路。

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

代码语言:javascript
复制
// 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)

是否有一种方法来过滤第一个查询中的关系之间的节点?

代码语言:javascript
复制
MATCH p=(n)-[*]->(n)
WHERE n.postId = 71 //postId is a node property
RETURN nodes(p)

重要说明:

  • 我知道如何限制路径的长度(通过WHERE ()约束或使用变长关系)
EN

回答 3

Stack Overflow用户

发布于 2017-09-01 19:44:49

你试过使用filter()none()吗?我认为我正确地理解了您的问题,但下面是我如何使用上述功能。(如果这是关的,那就顺势而行。)

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

代码语言:javascript
复制
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);

需要使用可变长度查询,因为:phone_number_of指针可以来自扩展名(链接到电话号码)或电话号码本身。箭头方向不重要,您可以反转它们中的任何一个,然后尝试下面的查询。

(在我的情况下,限制查询的长度是显而易见的解决方案,例如 匹配路径=(p:Person)-*1.3-(n:PhoneNumber)返回节点(路径); 但这不是OP的问题。)

(1)从人到电话号码的每一条可能的路径(为可读性而编辑):

代码语言:javascript
复制
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()消除冗余:

代码语言:javascript
复制
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()从返回路径中删除特定节点:

代码语言:javascript
复制
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]                                                      │
└──────────────────────────────────────────────────────────────┘
票数 2
EN

Stack Overflow用户

发布于 2016-08-31 20:46:53

您可能需要尝试APOC,特别是图算法部分中的allSimplePaths函数。简单路径不应该有重复的节点。

编辑

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

但是,如果将结束节点定义为周期中的第二到最后一步,那么所有与开始节点有定向关系的开始节点都应该能够得到结果(尽管路径显然不会包括对开始节点的最后遍历以完成周期)。

票数 0
EN

Stack Overflow用户

发布于 2016-08-31 22:22:04

虽然这可能不像@InverseFalcon建议的那样使用allSimplePaths APOC过程(我还没有尝试过),但在纯Cypher中可以获得简单的路径:

代码语言:javascript
复制
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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39258523

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档