【问题标题】:Creating Family Tree with Neo4J使用 Neo4J 创建家谱
【发布时间】:2015-01-07 20:01:16
【问题描述】:

我在 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 cypherneo4j cypher nested collect 最终将所有父节点组合在一起,用于我正在搜索的主子节点。

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

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

添加示例查询:

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

此查询返回五代每个父代的列表,但不是显示层次结构,而是将“Bob”列为每个关系的子代。是否有一个 Cypher 查询至少可以显示数据中的每个关系?我可以从那里根据需要对其进行格式化...

【问题讨论】:

  • 请提供更多信息;您使用的是 REST API 还是嵌入式数据库?如果您使用的是 REST API,您的问题可能会简化为将 REST API 吐出的 JSON 转换为您正在寻找的这种结构的任务。 neo4j.com/docs/stable/rest-api.html

标签: json neo4j


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    你也可以看看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
    

    另请参阅密码参考卡:http://neo4j.com/docs/stable/cypher-refcard 和在线培训http://neo4j.com/online-training,了解有关 Cypher 的更多信息。

    别忘了

    create index on :Person(FirstName);
    

    【讨论】:

      【解决方案3】:

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

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

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

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

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

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

      确保在会员 ID 上有一个索引!

      【讨论】:

      • 这与我要找的很接近。有没有办法通过单个查询生成集合?假设我想从一个特定的人那里看到四五代人的树。我可以得到图表来显示数据——如果可能的话,我只需要一种通过密码对其进行变形的方法。否则,我将不得不坚持使用从基本查询返回的原始数据,并且必须将其处理成我正在寻找的格式。
      • 可能只使用 cypher 就可以获得它,但我怀疑这不值得。
      • 哦,对不起,我看错了。我以为您想使用 JSON 并将其转换为带有密码的 neo4j 数据库,但您想要相反
      【解决方案4】:

      到目前为止,我发现获取所需数据的唯一方法是实际返回关系信息,如下所示:

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

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

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

      【讨论】:

      • 我在迈克尔写他的时候写了这个答案:) 两者都在同一条轨道上,所以给了他解决的答案。
      猜你喜欢
      • 1970-01-01
      • 2015-12-10
      • 1970-01-01
      • 2020-12-06
      • 1970-01-01
      • 2023-03-24
      • 2015-02-24
      • 2015-09-23
      • 1970-01-01
      相关资源
      最近更新 更多