通过Cypher中的多个路径地址选择节点列表

时间:2017-05-23 14:24:01

标签: neo4j cypher

考虑关注Cyphers:

MATCH (n{name: "John"})-[:Colleague]-(m) RETURN m;

此查询查找Colleague(s)的{​​{1}}。现在另一个:

John(s)

这个MATCH (n{name: "John"})-[:Friend]-()-[:Colleague]-(m) RETURN m; Colleague(s) John(s)'。现在是最后一个:

Friend(s)

最后,这个人找到MATCH (n{name: "John"})-[:Colleague]-()-[:Friend]-(m) RETURN m; Friend(s)的{​​{1}}。我正在寻找的是Cypher查询,它查找给定查询找到的所有节点的并集。

请注意,这只是一个例子。我在这里问的实际问题是如何使用多个路径找到一组节点?类似的东西:

John(s)'

5 个答案:

答案 0 :(得分:4)

在这种特殊情况下,您可以使用具有多种关系类型的可变长度关系。但是,为了防止不良路径(同事,朋友的朋友和朋友的同事),我们必须做一些额外的过滤,以确保路径中至少有一个同事关系。

MATCH (n{name: "John"})-[r:Colleague|Friend*1..2]-(m) 
WHERE 'Colleague' in [rel in r | type(rel)]
RETURN m;

另外,我强烈建议您在节点上使用标签,并在标签/名称组合上使用索引,这样您对John节点的查找速度很快,而不必检查图中的每个节点。 / p>

这个查询不像执行UNION的查询那样高效,但是通过索引查找和只有两次遍历,关系不是太多,它应该可以正常工作。

答案 1 :(得分:2)

如何简单地使用UNION?试试吧:

MATCH (n{name: "John"})-[:Colleague]-(m)
RETURN m as node

UNION

MATCH (n{name: "John"})-[:Friend]-()-[:Colleague]-(m)
RETURN m as node

UNION

MATCH (n{name: "John"})-[:Colleague]-()-[:Friend]-(m)
RETURN m as node

答案 2 :(得分:2)

您可以跨多个匹配重用变量来引用同一节点(JOIN模式)。实施例

MATCH (n{name: "John"})-[:Colleague]-(m)
MATCH (n)-[:Friend]-()-[:Colleague]-(m)
MATCH (n)-[:Colleague]-()-[:Friend]-(m)
RETURN m;

在这里," John"匹配一次,并用作每个匹配的开始,m是每个匹配的有趣节点的连接。如果" John"有多个实例,则此查询将分别处理所有这些实例。如果所有" Johns"应该被视为同一个人,而不仅仅是重用n。

如果你想要UNION而不是JOIN,你可以像这样收集它们

MATCH (n{name: "John"})
OPTIONAL MATCH (n)-[:Colleague]-(c)
OPTIONAL MATCH (c)-[:Friend]-(fc)
OPTIONAL MATCH (n)-[:Friend]-()-[:Colleague]-(fc)
WITH c+collect(fc)+collect(cf) AS nodez
UNWIND nodez AS m
RETURN DISTINCT m;

答案 3 :(得分:1)

为处理UNION查询添加单独的答案,同时保留处理联合结果的能力。

我们实际上有一篇关于post-UNION processing的知识库文章,其中有几种不同的方法。

使用APOC程序,您可以在apoc.cypher.run()内执行UNION,并获取返回的联合结果并继续对它们进行操作。

答案 4 :(得分:1)

这个简单的查询应该有效:

MATCH p=({name: "John"})-[:Friend*0..1]-()-[:Colleague]-()-[:Friend*0..1]-(m) 
WHERE LENGTH(p) <= 2
RETURN m;

它使用可变长度模式*0..1使Friend关系可选。 WHERE子句筛选出长度超过2个关系的路径。