在 neo4j 中读取 csv 时根据 ID 创建和推断关系

create and infer relationships based on ID when reading in a csv in neo4j

我有一个简单的 csv,有 4 行,看起来像这样:

+------------+-------------+------------+-------------+
|     ID     |      Name   |  FatherID  |  MotherID   |
+------------+-------------+------------+-------------+
| 1          | Mom Doe     |            |             |
| 2          | Dad Doe     |            |             |
| 3          | Big Sis     |  2         |  1          |
| 4          | Lil Bro     |  2         |  1          |
+------------+-------------+------------+-------------+

我正在尝试制作一个家谱,它看起来像这样:

这里的诀窍是我必须仅基于两件事来创建这些关系:FatherIDMotherID。这是可行的。但它需要以某种有条件的方式应用关系。

这是我尝试过的方法,但没有用:

LOAD CSV WITH HEADERS FROM
'file:///Users/.../import_for_Neo4j.csv' AS line
WITH line
CREATE (person:Person {id:line.ID})
SET person.Name=line.Name,
    person.MotherID=line.MotherID,
    person.FatherID=line.FatherID
WITH person
CREATE (a:Person {Name:'Mom Doe'})-[:SPOUSE]->(b:Person {Name:'Dad Doe'})
RETURN a 

但后来我意识到,即使这确实有效,又有什么意义呢?我必须输入 hand-type 每个家庭成员的姓名,这首先会否定加载 csv 的全部意义。如果是这样的话,我还不如在 Sublime 中手动输入所有内容,然后跳过读取 csv。

我的一个想法是让 FatherIDMotherID 为 NULL 的人成为 SPOUSE,但如果家谱有祖父母,那将行不通。

解决方案似乎非常棘手 -- 也许首先创建所有节点并创建 SIBLING 关系。然后遍历 csv 并生成 CHILD 关系?

有没有什么方法可以让我大体吸收 csv 并创建这个简单的图表?

感谢阅读本文。

这远非高效,具体取决于您的数据集,这将需要进行大量调整,但对于这个基本数据集,它正在运行:

LOAD CSV WITH HEADERS FROM
'file:///test.csv' AS line
WITH line
CREATE (p:Person {id: line.id})
SET p.name = line.name, p.motherId = line.motherId, p.fatherId = line.fatherId
WITH p
MATCH (p1:Person), (p2:Person)
WHERE p.fatherId = p1.id AND p.motherId = p2.id
MERGE (p1)-[:SPOUSE]->(p2);

效率问题会出在MATCH部分的笛卡尔积

我又增加了一个技巧,我把空的爸爸和妈妈的ID填满了零。

query result screenshot

已更新

与childrenparent关系:

LOAD CSV WITH HEADERS FROM
'file:///test.csv' AS line
WITH line
CREATE (p:Person {id: line.id})
SET p.name = line.name, p.motherId = line.motherId, p.fatherId = line.fatherId
WITH p
MATCH (p1:Person), (p2:Person)
WHERE p.fatherId = p1.id AND p.motherId = p2.id
MERGE (p1)-[:SPOUSE]->(p2)
WITH p
MATCH (father:Person)
WHERE p.fatherId = father.id
MERGE (p)-[:PARENT {type: 'FATHER'}]->(father)
WITH p
MATCH (mother:Person)
WHERE p.motherId = mother.id
MERGE (p)-[:PARENT {type: 'MOTHER'}]->(mother);

不需要SIBLING关系,因为您可以通过匹配共享parent的人来确定兄弟姐妹关系。

这是一种可能适合您需要的方法。

注意:我选择使用 FATHERMOTHER 关系而不是 CHILD,以保留 CSV 文件中的语义信息。如果您愿意,可以简化我的回答,只使用 CHILD

第 1 步:生成所有 Person 个节点

LOAD CSV WITH HEADERS FROM 'file:///Users/.../import_for_Neo4j.csv' AS line
MERGE (p:Person {id: line.ID, name: line.Name});

请注意,我使用 MERGE 而不是 CREATE,以避免创建重复项。

第 2 步:生成所有关系(父亲、母亲、配偶)

LOAD CSV WITH HEADERS FROM 'file:///Users/.../import_for_Neo4j.csv' AS line
MATCH (p:Person {id: line.ID})
WITH p, line
OPTIONAL MATCH (m:Person {id: line.MotherID})
FOREACH (x IN CASE WHEN m IS NULL THEN [] ELSE [1] END | MERGE (p)-[:MOTHER]->(m))
WITH p, m, line
OPTIONAL MATCH (f:Person {id: line.FatherID})
WITH p, m, f
FOREACH (x IN CASE WHEN f IS NULL THEN [] ELSE [1] END | MERGE (p)-[:FATHER]->(f))
FOREACH (y IN CASE WHEN m IS NULL OR f IS NULL THEN [] ELSE [1] END | MERGE (m)-[:SPOUSE]->(f))

结果如下,带有您的示例数据:

寻找兄弟姐妹

以下是找到“Lil Bro”的所有兄弟姐妹的方法:

MATCH (child:Person {name:'Lil Bro'})-[:MOTHER|FATHER]->()<-[:MOTHER|FATHER]-(sibling)
RETURN child, COLLECT(DISTINCT sibling)