【问题标题】:Cypher - neo4j find recursive end nodesCypher - neo4j 找到递归结束节点
【发布时间】:2015-05-08 18:06:05
【问题描述】:

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

我目前正在手动执行此操作,但需要递归类型的语句来简化和扩展。这是我到目前为止所拥有的,并带有一个描述我需要的返回语句。

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 

path,直到没有Type2指向Type1,返回这些Type1的名字。

【问题讨论】:

  • 所以要返回所有没有Rel3关系的Type1节点?

标签: recursion neo4j cypher graph-databases


【解决方案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 确实是“在顶部”。

用你自己的relTypes 和标签自定义这个,你应该能够遵循这个模式。

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

【讨论】:

  • 假设模型中没有“中间”对象,这是一个很好的答案。我不确定 cypher 是否具有处理这种递归多关系遍历的语法。请参阅我的解决方法的答案,因为它只需要一个额外的 create 语句,然后是您的解决方案。
【解决方案2】:

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

对不起,糟糕的类型掩蔽!我的别名应该更有创意。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多