【问题标题】:How to realize a nested tree in Neo4j?Neo4j中如何实现嵌套树?
【发布时间】:2014-10-08 14:04:43
【问题描述】:

我刚刚开始使用 Neo4j 和图形数据库,并且想知道嵌套分层树是否是 Neo4j 的一个很好的用例。一个常见的例子是一组嵌套的 cmets。例如:

 - Article
  - Comment 1 on Article
     - Comment 2 on Comment 1
     - Comment 3 on Comment 1
         - Comment 4 on Comment 3
  - Comment 5 on Article

据我了解,文章和 cmets 都是节点。每个评论都会有父子关系。获取文章(1 和 5)上的所有直接 cmets 将很容易。但是检索整个集合怎么样?

请原谅使用外行术语。我认为这样更好,而不是在混淆每个人的同时尝试使用适当的词。

【问题讨论】:

    标签: neo4j graph-databases


    【解决方案1】:

    好吧,因为trees actually are graphs 使用图形数据库存储树似乎完全适合我。什么会表现最好取决于您的数据访问模式,但基本上树只是图的一种特殊化。

    是的,在您的情况下,“树中的元素”将是节点,而“嵌套”将是关系。因此,您可以通过以下方式模拟您的示例:

    CREATE (root:Article {label: "Article"}),
           (c1:Comment {label: "Comment 1"}),
           (c1a:Comment {label: "Comment 2 on comment 1"}),
           (c1b:Comment {label: "Comment 3 on comment 1"}),
           (c1b1:Comment {label: "Comment 4 on comment 3"}),
           (c2:Comment {label: "Comment 5 on article"}),
           (root)<-[:reply]-(c1),
           (c1)<-[:reply]-(c1a),
           (c1)<-[:reply]-(c1b),
           (c1b)<-[:reply]-(c1b1),
           (root)<-[:reply]-(c2);
    

    这只是创建了一堆节点和关系,模仿您提供的结构。在这里,我选择始终使用:reply 来连接事物。

    现在,“得到一切”只是意味着遍历我们创建的所有:reply 关系:

    MATCH p=(a:Article {label: "Article"})<-[:reply*1..]-(otherThing) 
    WITH nodes(p) as nodes
    RETURN nodes[length(nodes)-2] as InResponseTo, 
           nodes[length(nodes)-1] as CommentOrReply;
    

    此查询的作用是遍历任意数量的:reply 链接(从根“文章”开始)。然后它只查看该路径中的节点,并返回最后一项 (CommentOrReply) 及其响应的内容(倒数第二项)。

    结果如下:

    +-------------------------------------------------------------------------------------+
    | InResponseTo                             | CommentOrReply                           |
    +-------------------------------------------------------------------------------------+
    | Node[18]{label:"Article"}                | Node[19]{label:"Comment 1"}              |
    | Node[19]{label:"Comment 1"}              | Node[20]{label:"Comment 2 on comment 1"} |
    | Node[19]{label:"Comment 1"}              | Node[21]{label:"Comment 3 on comment 1"} |
    | Node[21]{label:"Comment 3 on comment 1"} | Node[22]{label:"Comment 4 on comment 3"} |
    | Node[18]{label:"Article"}                | Node[23]{label:"Comment 5 on article"}   |
    +-------------------------------------------------------------------------------------+
    

    这就是你遍历整棵树的方式。

    编辑 - 值得一提的是,“可变长度路径匹配”,在上面的查询中只是这一点:&lt;-[:reply*1..]- 对我来说是图表的三大卖点之一数据库。正是图形数据库使图形数据库变得非常容易,而您的大多数其他替代方案(例如关系数据库)都变成了曲折痛苦的练习。所以如果你需要做那种事情(比如这里,组装一棵整棵树),我会声称它支持图形数据库,因为你在它的基本优势领域使用它。

    【讨论】:

    • 如果您想了解更多树的用例,请查看:jexp.de/blog/2014/04/importing-forests-into-neo4jblog.bruggen.com/search?q=hierarchy
    • 非常感谢您的详细解答!我目前正试图弄清楚如何从这个结果中检索嵌套散列,例如在 JSON 中。但这并不是一个真正的数据库问题……总的来说,一切看起来都比使用 MySQL 时必须提出的嵌套集合方法快得多。
    • 是的;在 mysql 中,常见的模式是只有一个表用于连接自身的节点 - 检查 3-4 之间的深度变得非常困难。
    • 顺便说一句,如果您不需要在 MATCH 子句中进一步引用节点,您可以使用 () 而不是 (otherThing)。刚学会。
    • 对于没有明确标签的根节点的人来说,根节点可以用WHERE NOT ()--&gt;(a)绑定到实际的根节点
    【解决方案2】:

    如果嵌套树完全是有向图并且没有循环(即有向无环图=DAG),那么您可以考虑在关系数据库中使用传递闭包方法。这些允许通过多个嵌套级别进行非常快速的查询并找到多个交叉点。他们有 n 平方问题,所以有很多行,但是使用 bigint 索引,查询运行得很快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-04
      • 1970-01-01
      • 2023-03-29
      • 2019-09-21
      • 2011-05-06
      • 2018-10-03
      • 2012-06-26
      相关资源
      最近更新 更多