使用 Neo4J 创建家谱

Creating Family Tree with Neo4J

我在 Neo4J 中有一组家谱数据,我正在尝试构建一个 Cypher 查询来生成类似于以下内容的 JSON 数据集:

{Name:  "Bob",
      parents: [
          {Name:  "Roger",
             parents: [
                Name: "Robert",
                Name: "Jessica"
             ]},
          {Name:  "Susan",
             parents: [
                Name: "George",
                Name: "Susan"
             ]}
      ]}

我的图表在 MEMBER 节点之间具有 PARENT 的关系(即 MATCH (p.Member)-[:PARENT]->(c.Member) )。我发现 Nested has_many relationships in cypher and neo4j cypher nested collect 最终将所有 parent 分组到我正在搜索的主要 child 节点。

根据反馈添加一些清晰度:

每个成员都有一个唯一的标识符。工会目前都与 PARENT 关系相关联。一切都被索引,这样性能就不会受到影响。当我 运行 一个查询来返回节点图时,我得到了我期望的结果。我正在尝试 return 可用于 D3 可视化目的的输出。理想情况下,这将通过 Cypher 查询来完成,因为我正在使用 API 从正在构建的前端访问 neo4j。

添加示例查询:

MATCH (p:Person)-[:PARENT*1..5]->(c:Person)
WHERE c.FirstName = 'Bob'
RETURN p.FirstName, c.FirstName

此查询 return 是五个世代的每个 parent 的列表,但它没有显示层次结构,而是将 'Bob' 列为每个关系的 child。是否有一个 Cypher 查询至少可以显示数据中的每个关系?我可以根据需要对其进行格式化...

我建议构建一种方法,将您的数据展平到一个数组中。如果它们的对象没有 UUID,您可能希望在展平时为它们提供 ID,然后为每条记录设置一个 parent_id 键。

然后您可以 运行 它作为一组密码查询(向查询 REST API 发出多个请求,或者使用批处理 REST API)或者转储数据到 CSV 并使用 cypher 的 LOAD CSV 命令加载对象。

带有参数的示例密码命令是:

CREATE (:Member {uuid: {uuid}, name: {name}}

然后 运行再次使用父 ID 和子 ID 遍历列表:

MATCH (m1:Member {uuid: {uuid1}}), (m2:Member {uuid: {uuid2}})
CREATE m1<-[:PARENT]-m2

确保会员ID有索引!

系谱数据可能符合 GEDCOM 标准,包括两种类型的节点:Person 和 Union。 Person 节点有它的标识符和通常的人口统计信息。联合节点有一个 union_id 和关于联合的事实。在 GEDCOM 中,家庭是将这两者结合在一起的第三个元素。但是在 Neo4j 中,我发现在 Person 节点中也包含 union_id 是合适的。我用了5种关系:父亲、母亲、丈夫、妻子和child。然后,这个家庭有两个 parents 有一个向内向量,每个 child 有一个向外向量。该图像说明了这一点。这对于可视化连接和生成假设非常方便。例如,考虑附图和我的祖先 Edward G Campbell,他是 1917 年工会的产物,其中三个兄弟与 8944 工会的三个 Vaught 姐妹和两个 2945 工会的 Gaither 姐妹结婚。此外,在左上角,Mahala Campbell 如何与她结婚step-brother 约翰·格里尔·阿姆斯特朗。 Mahala 旁边是 Elizabeth Campbell,她与其他 Campbell 有婚姻关系,但很可能与他们有直接关系。同样,您可以假设右上角的 Rachael Jacobs 以及她与其他 Jacobs 的关系。 我使用批量插入,它可以在一分钟多一点的时间内填充约 30000 个 Person 节点和约 100,000 个关系。我有一个小的 .NET 函数,它 returns 来自数据视图的 JSon;这个通用解决方案适用于任何数据视图,因此它是可扩展的。我现在正在努力添加其他数据,例如位置 (lat/long)、文档(特别是联系人们的信息,例如人口普查)等。

到目前为止,我发现获得我正在寻找的数据的唯一方法是实际 return 关系信息,如下所示:

MATCH ft = (person {firstName: 'Bob'})<-[:PARENT]-(p:Person)
RETURN EXTRACT(n in nodes(ft) | {firstName: n.firstName}) as parentage
ORDER BY length(ft);

这将 return 一个我可以变形的数据集:

["Bob", "Roger"]
["Bob", "Susan"]
["Bob", "Roger", "Robert"]
["Bob", "Susan", "George"]
["Bob", "Roger", "Jessica"]
["Bob", "Susan", "Susan"]

你也可以看看 Rik van Bruggens Blog on his family data:

关于您的查询

您已经在此处创建了一个路径模式:(p:Person)-[:PARENT*1..5]->(c:Person)您可以将其分配给一个变量tree,然后对该变量进行操作,例如返回树,或 nodes(tree)rels(tree) 或以其他方式对该集合进行操作:

MATCH tree = (p:Person)-[:PARENT*1..5]->(c:Person)
WHERE c.FirstName = 'Bob'
RETURN nodes(tree), rels(tree), tree, length(tree),
       [n in nodes(tree) | n.FirstName] as names

另请参阅 Cypher 参考卡:http://neo4j.com/docs/stable/cypher-refcard and the online training http://neo4j.com/online-training 以了解有关 Cypher 的更多信息。

别忘了

create index on :Person(FirstName);