在我的ruby-on-rails应用程序中,我有嵌套的注释,可以嵌套任意长度。
我尝试了不同的存储方式:
使用自联接:
belongs_to :parent, :class_name => 'Comment', :foreign_key => 'parent_id'
has_many :children, :class_name => 'Comment', :foreign_key => "parent_id"
使用祖先宝石
等
但问题是,无论我使用什么,都会有一定数量的SQL语句。 (1声明获取所有根注释,然后为每个根的子节点添加1个语句,然后为所有子节点添加1个语句,等等)
有没有更有效的方法来实现这一目标?
Postgres 9.1,但希望向后兼容的解决方案是首选。
答案 0 :(得分:3)
您可以坚持使用parent_id
指针列并使用find_by_sql
和WITH RECURSIVE
查询,让数据库一次完成所有工作。像这样:
comments = Comment.find_by_sql(%Q{
with recursive tree(id) as (
select c.id, c.column1, ...
from comments c
where c.id in (#{roots.join(',')})
union all
select c.id, c.column1, ...
from comments c
join tree on c.parent_id = tree.id
)
select id, column1, ...
from tree
})
其中roots
将是一个Ruby数组,其中包含您感兴趣的根节点的id
。这将为您提供感兴趣的子树中的所有节点作为Comment实例。我过去曾经使用过这样的查询,而且即使是浅树,WITH RECURSIVE的速度也是迭代技术的两倍,我猜想更深的树木会看到更好的速度。
您正在使用的parent_id
结构对于大多数事物都非常方便,并且与ActiveRecord的工作方式相当吻合。此外,坚持使用当前的结构意味着您可以单独留下其余的应用程序。
WITH RECURSIVE可用于PostgreSQL 8.4及更高版本。
答案 1 :(得分:1)
看一下awesome_nested_set,我想你会喜欢它。