【问题标题】:Neo4j Cypher - Load Tree Structure from CSVNeo4j Cypher - 从 CSV 加载树结构
【发布时间】:2018-04-24 15:05:25
【问题描述】:

密码新手,我正在尝试加载具有 5 列的树结构的 csv。对于单行,每一项都是一个节点,第n+1列的每一个节点都是第n列节点的子节点。

例子:

CSV 列:Level1、Level2、Level3、Level4、Level5

结构:Level1_thing <--child_of-- Level2_thing <--child_of-- Level3_thing 等...

数据库是非规范化的,所以除了最底层之外的所有级别都有很多重复的节点名称。使用 cypher 加载此 csv 并从 csv 创建此树结构的最佳方法是什么?

抱歉,如果这个问题的格式不正确或被问到,我对堆栈溢出和图形数据库都是新手。

【问题讨论】:

    标签: csv neo4j tree cypher


    【解决方案1】:

    您正在搜索的是MERGE 命令。

    要完成您的脚本,您必须分两个阶段完成以实现最佳执行

    1) 如果节点不存在则创建节点

    USING PERIODIC COMMIT 
    LOAD CSV WITH HEADERS FROM "file:///my_file.csv" AS row
    MERGE (l5:Node {value:row.Level5})
    MERGE (l4:Node {value:row.Level4})
    MERGE (l3:Node {value:row.Level3})
    MERGE (l2:Node {value:row.Level2})
    MERGE (l1:Node {value:row.Level1})
    

    2) 如果关系不存在,则创建关系

    USING PERIODIC COMMIT 
    LOAD CSV WITH HEADERS FROM "file:///my_file.csv" AS row
    MATCH (l5:Node {value:row.Level5})
    MATCH (l4:Node {value:row.Level4})
    MATCH (l3:Node {value:row.Level3})
    MATCH (l2:Node {value:row.Level2})
    MATCH (l1:Node {value:row.Level1})
    MERGE (l5)-[:child_of]->(l4)
    MERGE (l4)-[:child_of]->(l3)
    MERGE (l3)-[:child_of]->(l2)
    MERGE (l2)-[:child_of]->(l1)
    

    并且首先,您需要在您的节点上创建一个约束,以方便MERGE 的工作。在我的例子中,它将是:

    CREATE CONSTRAINT ON (n:Node) ASSERT n.value IS UNIQUE;
    

    【讨论】:

    • CREATE INDEX ON :Node(value) 在这里应该足够了,因为 MERGE 负责处理唯一性问题。
    • 需要,但还不够。如果你需要一些独特的东西,你需要一个约束(它会在后台创建一个索引)
    • 感谢您的回答,这对我的数据集有很大帮助并快速运行。唯一当前的问题是我意识到有时 Level2 和 Level3 可能具有相同的名称,从而使节点成为它们自己的子节点。我知道这违反直觉,但如果可能的话,我想保持相同数量的关卡。不过,我可以从这里弄清楚。
    【解决方案2】:

    IIUC,您可以使用 Cypher 中的 LOAD CSV 函数来加载节点和关系。在您的情况下,您可以使用 MERGE 来处理重复项。您的示例应该以这种方式工作,并带有一些伪代码:

    LOAD CSV with HEADERS from "your_path" AS row
    MERGE (l1:Label {prop:row.Level1}
    ...
    MERGE (l5:Label {prop:row.Level1}
    MERGE (l1)<-[CHILD_OF]-(l2)<-...-(l5)
    

    基本上,您可以在读取带有标题的 .csv 文件时创建动态节点和关系。希望对您有所帮助。

    【讨论】:

      【解决方案3】:

      如果csv文件没有标题行,并且列顺序是固定的,那么你可以这样解决问题:

      LOAD CSV from "file:///path/to/tree.csv" AS row
      // WITH row SKIP 1 // If there is a headers, you can skip the first line
      // Pass on the columns:
      UNWIND RANGE(0, size(row)-2) AS i
        MERGE (P:Node {id: row[i]})
        MERGE (C:Node {id: row[i+1]})
        MERGE (P)<-[:child_of]-(C)
      RETURN *
      

      是的,在此之前添加索引确实值得:

      CREATE INDEX ON :Node(id)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-02
        • 1970-01-01
        相关资源
        最近更新 更多