当子节点有多个父节点时,如何避免使用Neo4J/Cypher进行大量冗余路径分析?

当子节点有多个父节点时,如何避免使用Neo4J/Cypher进行大量冗余路径分析?,neo4j,cypher,Neo4j,Cypher,这将返回距“id1”正好两代的所有唯一父代 当每个孩子只有一个家长时,这种方法很有效。但在我的数据中,一个节点可以有多个父节点(没有循环关系)。据 PROFILE MATCH (:LevelOne {id: "id1"})-[:ISCHILDOF*2..2]->(parent:LevelTwo) RETURN DISTINCT parent ORDER BY parent.id 由于只有几千个节点,这将导致数以千万计的路径组合,并且由于资源耗尽而导致一致性故障 比如说, 如果“

这将返回距“id1”正好两代的所有唯一父代

当每个孩子只有一个家长时,这种方法很有效。但在我的数据中,一个节点可以有多个父节点(没有循环关系)。据

PROFILE MATCH (:LevelOne {id: "id1"})-[:ISCHILDOF*2..2]->(parent:LevelTwo)
    RETURN DISTINCT parent ORDER BY parent.id
由于只有几千个节点,这将导致数以千万计的路径组合,并且由于资源耗尽而导致一致性故障

比如说,

如果“id1”是节点A,并且您希望它的所有父节点都在三代之外,那么您将为每个子节点“通过”D节点两次:ABDF、ACDF

避免这种冗余的一种方法是一次查询一代,例如从以下内容开始:

MATCH (:LevelOne {id: "id1"})-[:ISCHILDOF]->(parent:LevelTwo)
    RETURN DISTINCT parent ORDER BY parent.id
(不存在“*2..2”范围)

收集返回的父级,遍历它们以收集它们的ID,并使用它们查询下一代父级:

MATCH (:LevelOne {id: "id1"})-[:ISCHILDOF]->(parent:LevelTwo)
    WHERE child.id IN [
        'id1001',
        'id1002',
        'id1003',
        'id1004',
        'id1005',
        'id1006',
        'id1013',
        'id1014',
        'id1015',
        'id1016',
        'id1017']
    RETURN DISTINCT parent
    ORDER BY parent.id
根据需要对任意多个生成级别重复此操作

有没有更好、更标准的方法来实现这一点?

[更新]

老祖宗 如果您只需要搜索最老一代的祖先,那么这种方法应该适用于您。很容易生成任意代数的查询

假设要搜索距离
id
为“id1”的节点4代以外的祖先:

MATCH
子句的数量对应于生成的数量

将此方法演示5代

每一代的祖先(即使不是在通往最老一代的道路上) 如果您希望搜索每一代人的祖先,这种方法应该适用于您。下面的示例适用于4代人

注意:这种方法将列出每一代中的每一位祖先,甚至是那些不在通往最老一代的道路上的祖先


非常感谢。你能演示如何在多代人中返回祖先吗?我已经用一个数字对每一代的父代和祖先进行了后期修复(
parent1作为ancestor1
),但我不清楚如何返回的不仅仅是最深的祖先代(
返回不同的parent5作为ancestor5
)。类似于-,虽然我知道这种语法是错误的-
返回不同的ancestor2、ancestor3、ancestor4
。这要复杂得多-特别是如果您只想要沿着最老一代祖先的路径的祖先。查看每一代的所有祖先有点容易(但仍然很复杂)。我更新了我的答案,展示了如何查看每一代的所有祖先。感谢您的见解。我想我的选择是使用第一个查询,一次一代。
MATCH (:LevelOne {id: "id1"})-[:ISCHILDOF]->(parent:LevelTwo)
    WHERE child.id IN [
        'id1001',
        'id1002',
        'id1003',
        'id1004',
        'id1005',
        'id1006',
        'id1013',
        'id1014',
        'id1015',
        'id1016',
        'id1017']
    RETURN DISTINCT parent
    ORDER BY parent.id
MATCH (:LevelOne { id: "id1" })-[:ISCHILDOF]->(parent:LevelTwo)
WITH DISTINCT parent AS ancestor
MATCH (ancestor)-[:ISCHILDOF]->(parent:LevelTwo)
WITH DISTINCT parent AS ancestor
MATCH (ancestor)-[:ISCHILDOF]->(parent:LevelTwo)
WITH DISTINCT parent AS ancestor
MATCH (ancestor)-[:ISCHILDOF]->(parent:LevelTwo)
RETURN DISTINCT parent AS ancestor;
MATCH (:LevelOne { id: "id1" })-[:ISCHILDOF]->(parent:LevelTwo)
WITH COLLECT(DISTINCT parent) AS ancestors
WITH [ancestors] AS generations, ancestors UNWIND ancestors AS ancestor
MATCH (ancestor)-[:ISCHILDOF]->(parent:LevelTwo)
WITH generations, COLLECT(DISTINCT parent) AS ancestors
WITH generations+[ancestors] AS generations, ancestors UNWIND ancestors AS ancestor
MATCH (ancestor)-[:ISCHILDOF]->(parent:LevelTwo)
WITH generations, COLLECT(DISTINCT parent) AS ancestors
WITH generations+[ancestors] AS generations, ancestors UNWIND ancestors AS ancestor
MATCH (ancestor)-[:ISCHILDOF]->(parent:LevelTwo)
WITH generations, COLLECT(DISTINCT parent) AS ancestors
RETURN generations+[ancestors] AS generations;