儿童过滤父母

时间:2013-06-28 02:54:59

标签: sql ruby-on-rails ruby ruby-on-rails-3 activerecord

我正在做一个简单的博客应用程序 - 有帖子,通过posts_tags表有许多标签(我的模型如下)。我实现的是,如果用户点击标签,它将只显示带有该标签的帖子。我想要的是让用户能够选择另一个标签,它只会过滤到同时具有这两个标签的帖子,然后是第三个,然后是第四个等等。我在制作活动记录时遇到困难查询 - 特别是动态的。我得到的最接近的是下面列出的 - 但它在纯SQL中,我想至少在ActiveRecord Rubyland语法中使用它,即使它包含的复杂性。

此外,“有计数2”不起作用,它说“计数”不存在,即使我为其指定名称。但是,它输出在我的表中(计数背后的想法是,如果它包含的数字与我们搜索的标签数量一样多,那么理论上/理想情况下它包含所有标签)

我当前的测试SQL查询

select posts_tags.post_id,count(*) from posts_tags where tag_id=1 or tag_id=3 group by post_id ### having count=2

测试SQL的输出(我知道它不包含很多但只包含一些简单的种子数据)。

 post_id | count 
---------+-------
       1 |     2
       2 |     1

我的模特: /post.rb

class Post < ActiveRecord::Base
    has_many :posts_tags
    has_many :tags, :through => :posts_tags
end

/tag.rb

class Tag < ActiveRecord::Base
    has_many :posts_tags
    has_many :posts, :through => :posts_tags
end

/poststag.rb

class PostsTag < ActiveRecord::Base
    belongs_to :tag
    belongs_to :post
end

3 个答案:

答案 0 :(得分:1)

尝试:

Post.joins(:tags).where(tags: {id: [1, 3]}).select("posts.id, count(*)").group("posts.id").having("count(*) > 2")

答案 1 :(得分:0)

我认为“count = 2”不正确。它应该是“count(*)= 2”。您的查询将是

select post_id,count(post_id) 
from posts_tags 
where tag_id = 1 or tag_id = 3 
group by post_id 
having count(post_id) = 2

答案 2 :(得分:0)

通常,您希望在使用rails时远离编写原始sql。 Active Record有很好的帮助方法,可以让你的sql更具可读性和可维护性。

如果您只有几个标签,则可以为每个标签创建范围(http://guides.rubyonrails.org/active_record_querying.html#scopes

由于人们一次点击一个标签,您可以只查询每个标签,然后在阵列上使用&运算符。因为您已经从数据库中请求了完全相同的数据集,所以应该缓存查询结果,这意味着您只是在数据库中访问最新的查询。