在 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 |
+------------+-------------+------------+-------------+
我正在尝试制作一个家谱,它看起来像这样:
这里的诀窍是我必须仅基于两件事来创建这些关系:FatherID
和 MotherID
。这是可行的。但它需要以某种有条件的方式应用关系。
这是我尝试过的方法,但没有用:
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。
我的一个想法是让 FatherID
和 MotherID
为 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填满了零。
已更新
与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的人来确定兄弟姐妹关系。
这是一种可能适合您需要的方法。
注意:我选择使用 FATHER
和 MOTHER
关系而不是 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)
我有一个简单的 csv,有 4 行,看起来像这样:
+------------+-------------+------------+-------------+
| ID | Name | FatherID | MotherID |
+------------+-------------+------------+-------------+
| 1 | Mom Doe | | |
| 2 | Dad Doe | | |
| 3 | Big Sis | 2 | 1 |
| 4 | Lil Bro | 2 | 1 |
+------------+-------------+------------+-------------+
我正在尝试制作一个家谱,它看起来像这样:
这里的诀窍是我必须仅基于两件事来创建这些关系:FatherID
和 MotherID
。这是可行的。但它需要以某种有条件的方式应用关系。
这是我尝试过的方法,但没有用:
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。
我的一个想法是让 FatherID
和 MotherID
为 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填满了零。
已更新
与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的人来确定兄弟姐妹关系。
这是一种可能适合您需要的方法。
注意:我选择使用 FATHER
和 MOTHER
关系而不是 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)