如何返回与嵌套集的子项列表关联的记录?

时间:2011-02-12 04:46:19

标签: ruby-on-rails nested-sets has-and-belongs-to-many

Rails版本3.0.3,我是rails的新手,但已经在webdev中使用了很长时间。

我正在使用很棒的嵌套集。

我有表格“帖子”,“标签”和“labels_posts”

帖子has_and_belongs_to_many标签
标签has_and_belongs_to_many帖子

标签acts_as_nested_set

我有一个label_id,我希望获得与该标签及其子项关联的所有帖子,所有这些都是一个有序的结果集。

让我们说我有标签:“L1,L1.1,L1.1.1,L1.2,L2”

鉴于L1,并且知道因此我有L1,L1.1,L1.1.1和L1.2,我通常会运行查询:

select id, title
from posts
where exists (select * from labels_posts where labels_posts.post_id = posts.id and labels_posts.label_id IN ('L1', 'L1.1', 'L1.1.1', 'L1.2'))
order by created_at desc

此查询将返回与每个标签关联的所有帖子。

那么,有什么方法可以做到这一点?


修改

所以,这是我的控制器

@label = Label.find(params[:label])
@posts = Post.all.select do |post|
  post.label_ids.include?(@label.self_and_descendants.map(&:id))
end

这是rails服务器输出

Label Load (0.5ms)  SELECT "labels".* FROM "labels" WHERE ("labels"."cached_slug" = 'caribbean') LIMIT 1
Post Load (0.6ms)  SELECT "posts".* FROM "posts"
Label Load (0.2ms)  SELECT "labels".id FROM "labels" INNER JOIN "labels_posts" ON "labels".id = "labels_posts".label_id WHERE ("labels_posts".post_id = 1 )
Label Load (0.8ms)  SELECT "labels".* FROM "labels" WHERE ("labels"."lft" >= 1 AND "labels"."rgt" <= 8) ORDER BY "lft"
Label Load (0.1ms)  SELECT "labels".id FROM "labels" INNER JOIN "labels_posts" ON "labels".id = "labels_posts".label_id WHERE ("labels_posts".post_id = 2 )
CACHE (0.0ms)  SELECT "labels".* FROM "labels" WHERE ("labels"."lft" >= 1 AND "labels"."rgt" <= 8) ORDER BY "lft"

我不确定select方法是否需要。


编辑答案:

所以这是我到达的答案

@label = Label.find(params[:label])
@posts = Post.order('posts.created_at desc').where('labels_posts.label_id IN (?)', @label.self_and_descendants.map(&:id)).includes(:labels)

2 个答案:

答案 0 :(得分:2)

Post.all(:conditions => "id = labels_posts.post_id AND label_posts.label_id in('L1', 'L1.1', 'L1.1.1', 'L1.2')", :include => [:label => labels_posts], :order => :created_at)

答案 1 :(得分:0)

让我们首先收集Label(label_id)及其子代的ID。

然后使用Ruby Array Select方法选择与相应标签关联的帖子。

label_ids = Label.find(label_id).children.map(&:id).push(label_id)
posts = Post.all.select{|post| post.label_ids.include?(label_ids)}