如何在Neo4j中实现嵌套树?

5

我刚开始接触Neo4j和图形数据库,想知道嵌套层次树是否适合在Neo4j中使用。一个常见的例子是嵌套评论。例如:

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

据我理解,文章和评论各自都是节点。每个评论都有父子关系。获取文章的所有直接评论(1和5)很容易。但如何检索整个集合呢?

请原谅使用了通俗易懂的术语。我认为这样比试图使用恰当的词汇而让所有人感到困惑更好。

2个回答

7

嗯,因为实际上树是图形,所以使用图形数据库来存储树在我看来是完全合适的。最佳表现取决于您的数据访问模式,但基本上树只是图形的一种特化。

是的,在您的情况下,“树中的元素”将是节点,“嵌套”将是关系。因此,这是您可能会模拟您的示例的方法:

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链接(从根节点"Article"开始)。然后它只查看该路径中的节点,并返回最后一项(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"}   |
+-------------------------------------------------------------------------------------+

那么这就是如何遍历整个树的方法。 编辑 - 就我而言,“可变长度路径匹配”,在上面的查询中只是这部分:<-[:reply*1..]-,是图数据库的前三大卖点之一。正是由于此,图形数据库使得大多数其他选择(如关系型数据库)变得非常艰难。因此,如果您需要做这种事情(例如在此处组装整个树),我会认为这表明支持使用图形数据库,因为您正在使用其基本强项所在的领域。

2
如果你想看更多关于树的用例,请查看以下链接:http://jexp.de/blog/2014/04/importing-forests-into-neo4j/ 和 http://blog.bruggen.com/search?q=hierarchy - Michael Hunger
非常感谢您详细的回答!我目前正在尝试弄清楚如何从此结果中检索嵌套哈希,例如在JSON中。但这并不是真正的数据库问题...总的来说,与使用MySQL时必须想出的嵌套集方法相比,一切看起来都快得多。 - Ole Spaarmann
是的,在 MySQL 中,常见的模式是只有一个节点表与自身连接 - 在深度检查达到 3-4 时变得非常困难。 - FrobberOfBits
顺便提一下,如果在MATCH子句中不需要进一步引用节点,则可以使用()而不是(otherThing)。我刚学会了这个。 - Ole Spaarmann
对于那些没有为其根节点设置明确标签的人,只需使用 WHERE NOT ()-->(a) 将根节点绑定到实际根节点即可。 - Tezra

-1
如果嵌套树完全是有向图且没有循环(即,有向无环图=DAG),则可以考虑在关系型数据库中使用传递闭包方法。这些方法允许快速查询多个嵌套级别和多个交集。它们存在n平方问题,因此有很多行,但使用bigint索引查询运行速度很快。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接