Cypher - neo4j找到递归的末端节点

时间:2015-05-08 18:06:06

标签: recursion neo4j cypher graph-databases

我试图找到给定节点类型的所有开始节点,从我的数据库中的任何节点开始。这些节点没有指向它们的关系。

我目前正在手动执行此操作,但需要使用递归类型的语句来简化和扩展。这是我到目前为止所做的,返回声明描述了我的需要。

MATCH ((d1:Type1 {Name: "test1"}))
MATCH ((t1:Type2)-[:Rel1]->(h1:Type3))
MATCH ((d1)<-[ud1:Rel3]-(t1))
OPTIONAL MATCH ((h1)<-[:Rel1]-(t2:Type2))
OPTIONAL MATCH ((t2)<-[:Rel2]-(d2:Type1))
OPTIONAL MATCH ((d2)<-[ud2:Rel3]-(t3:Type2))
OPTIONAL MATCH ((t3)-[:Rel1]->(h2:Type3))
OPTIONAL MATCH ((h2)<-[:Rel1]-(t4:Type2))
OPTIONAL MATCH ((t4)<-[:Rel2]-(d3:Type1))
OPTIONAL MATCH ((d3)<-[ud3:Rel3]-(t5:Type2))

RETURN DISTINCT Type1.Name where there is no Rel3 relationship

这里的问题是导航递归

Type1 < -  Type2 -> Type3 <- Type2 < - Type1 < - Type2 -> Type3 <- Type2 

路径,直到没有指向Type1的Type2,并返回这些Type1的名称。

2 个答案:

答案 0 :(得分:1)

您的查询示例非常复杂,并且包含使其难以理解的替代类型。

我认为这归结为非常简单的事情,你应该试试这个:

MATCH (startingPoint:Type1 { name: "test1" })
MATCH (startingPoint)-[:relType*]->(headNode)
OPTIONAL MATCH (headNode)-[f:relType]->()
WHERE f is null;

所以这一切都是从startingPoint到任意数量的关系匹配到headNode。我们怎么知道headNode真的刚开始?因为我们坚持OPTIONAL MATCH它不能连接到更上游的任何其他东西。我们尝试匹配另一个上游匹配,然后坚持必须缺少WHERE子句,因此headNode确实“在顶部”。< / p>

使用您自己的relTypes和标签对其进行自定义,您应该能够遵循此模式。

更广泛地说,当您询问某个开始节点并且没有某些关系时,See also this related question

答案 1 :(得分:1)

FrobberOfBits有一个很好的答案,但没有解决递归浏览多个节点类型的需要。我还没有看到允许在Cypher中进行这种类型的递归查询的语法。

解决方法是使用复杂遍历创建一个新关系,然后使用FrobberOfBits解决方案找到头节点。

以下是我提出的建议:

MATCH ((d1:Type1))
MATCH ((q1:Type2)-[:Rel1]->(p1:Type3))
MATCH ((d1)<-[ud1:Rel2]-(q1))
MATCH ((p1)<-[:Rel1]-(q2:Type2))
MATCH ((q2)<-[:Rel3]-(d2:Type1))
WITH  distinct d1 as child,d2 as parent
CREATE (child)<-[:ParentOf]-(parent)

这会在两个Type1之间创建一个新的关系类型,无需递归浏览不同的节点类型,只需在单个节点类型上允许树遍历(如FrobberOfBits巧妙解释)

以下是我使用问题中的类型和上面的create语句生成的查询,其中包含Fibber的替代语法。

MATCH((d1:Type1 {Name: "test1"}))
OPTIONAL MATCH ((d1)<-[r1:Rel1*]-(d2:Type1))
WHERE NOT (d2)<--()
return distinct d2.Name

抱歉可怜的类型掩盖!我的别名我应该更有创意。