我需要在 Rails 3 应用程序中构建一个嵌套评论系统,允许对许多模型(文章、帖子等)进行评论,并且正在讨论沿着 这篇文章。有一些可用的宝石,例如 acts_as_commentable_with_threading 和 awesome_nested_set,但它们对于我的需求来说感觉有些臃肿。
- 我需要能够向多个模型添加评论
- 我需要能够向评论添加评论,无限深
- 我需要能够有效地检索帖子、文章等的所有后代
- 我需要能够有效地呈现 我的
问题是,如果我推出自己的解决方案,我可能会面临哪些潜在的问题。我想避免走一条路只会到达死胡同。我最初的担忧与有效查询儿童有关。例如,获取文章后代评论(子项和子项的子项)的列表。
有人对此有意见吗?谢谢。
I need to build a nested comments system in a Rails 3 application that allows for comments on many models (articles, posts, etc) and am debating rolling my own solution along the lines of this post. There are gems available like acts_as_commentable_with_threading with awesome_nested_set, but they feel bloated for my needs.
- I need to be able to add comments to multiple models
- I need to be able to add comments to comments, infinitely deep
- I need to be able to efficiently retrieve all descendants for a post, article, etc
- I need to be able to efficiently present the comments in their appropriate nesting
My question is, were I to roll my own solution what potential hiccups I could face. I want to avoid going down one path only to reach a dead end. My initial concerns relate to efficiently querying for children. Say, for instance, getting a list of an articles descendant comments (children and children of children).
Anyone have input on this? Thanks.
发布评论
评论(3)
您可以执行两种嵌套:树和嵌套集。
acts_as_tree
仅存储parent_id
,因此写入新条目非常快,但您必须递归遍历 id 编号链才能获取所有子项的列表。当您需要进行大量阅读时,这不是一个好的选择。awesome_nested_set
记录三位信息:parent_id
、lft
和rgt
。计算左侧值和右侧值,以便它们包含该条目的所有子 ID。这对于读操作来说非常快,但对于写操作来说却很慢。对于你的情况,我认为
awesome_nested_set
更合适。您可能认为这似乎有点过分了,但嵌套集合很快就会变得复杂。您需要使用嵌套集合模式来有效地查询子项。您只需要使用两种方法来渲染整个评论树:迭代
Comment.roots
并为每个评论渲染comment.children
。要保存嵌套评论,只需填写
parent_id
即可,awesome_nested_set
将完成剩下的工作。我认为推出自己的解决方案不会比这更优雅。更新:
awesome_nested_set
似乎有一段时间没有更新了。请查看 ancestry。做的事情基本上是一样的。There are two kinds of nesting you can do: a tree and a nested set.
acts_as_tree
stores only aparent_id
and so it is really fast to write new entries, but you have to recursively walk the chain of id numbers to get a list of all the children. This is not a good choice when you need to do lots of reads.awesome_nested_set
records three bits of information:parent_id
,lft
andrgt
. The left and right values are calculated so that they contain all the children ids for that entry. This is very fast for read operations but slower to write.In your case I think
awesome_nested_set
is more appropriate. You might think it seems overkill, but nested sets get complicated in a hurry. You need to use the nested set pattern to efficiently query children.You only need to use two methods to render the entire tree of comments: iterate over
Comment.roots
and for each comment, rendercomment.children
.To save a nested comment, simply fill in the
parent_id
andawesome_nested_set
will do the rest. I don't think rolling your own solution will be any more elegant than this.Update: Looks like the
awesome_nested_set
hasn't been updated in some time. Check out ancestry instead. Does basically the same things.是的,树结构是一个好主意 - 然而,最关心的是查询执行本身,我不认为大多数树实现作为 gem 考虑到这一点,而嵌套集是好的 - 我认为如果发生了非常糟糕的事情,就写入操作而言过于复杂。
我会查看 递归 CTE - 虽然与数据库无关,但它为您提供了一个很好的数据结构来使用,而无需跟踪额外的属性。
A tree structure, yes, is a good idea - however it is the query execution itself that is of the utmost concern and i don't think most tree implementations as a gem take this into account and whilst nested set is alright - i reckon if something really bad happened, its overcomplicated in terms of write operations.
I'd check out Recursive CTEs - whilst not database agnostic, it gives you a nice data structure to work with without having to have extra attributes to track.
我曾经通过将以下字段添加到评论表中来执行类似的操作:
Attached_to_controller (string)
Attached_to_id (int)
然后,在显示时,我将根据这两个字段对评论索引和过滤器进行 AJAX 调用。
当然,在创建注释时,您需要为这些字段传递适当的值。
I used to do something like this by adding the following fields to the comments table:
attached_to_controller (string)
attached_to_id (int)
Then when showing I would make an AJAX call to the comments index and filter based on these two fields.
Of course, when creating comments you need to pass the appropriate values for these fields.