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

时间:2016-01-13 18:07:06

标签: neo4j cypher

这将返回与“id1”完全相距两代的所有唯一父母。

MATCH (:LevelOne {id: "id1"})-[:ISCHILDOF*2..2]->(parent:LevelTwo)
    RETURN DISTINCT parent ORDER BY parent.id

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

PROFILE MATCH (:LevelOne {id: "id1"})-[:ISCHILDOF*2..2]->(parent:LevelTwo)
    RETURN DISTINCT parent ORDER BY parent.id

只有几千个节点,这导致数以千万计的路径组合,以及由于资源耗尽导致的一致性故障。

例如,鉴于此

relations

如果“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

根据需要为多个世代级别重复此操作。

是否有更好,更标准的方法来实现这一目标?

1 个答案:

答案 0 :(得分:2)

[更新]

最老一代的祖先

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

假设您要搜索距id为" id1"

的节点4代的祖先
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子句的数量对应于世代数。

This console演示了这种方法5代。

每一代的祖先(即使没有走向老一代的道路)

如果您希望搜索每一代的祖先,这种方法应该适合您。下面的例子是4代。

注意:此方法将在每一代中列出每个祖先,即使是那些没有通往最老一代的人。

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;