【问题标题】:Filtering Parents by Children按孩子过滤父母
【发布时间】:2013-06-28 02:54:58
【问题描述】:

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

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

我当前的测试 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

【问题讨论】:

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


    【解决方案1】:

    试一试:

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

    【讨论】:

    • 这太神奇了。我会花很长时间来解决这个问题!非常感谢
    【解决方案2】:

    我认为“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
    

    【讨论】:

      【解决方案3】:

      一般来说,您希望在使用 rails 时避免编写原始 sql。 Active Record 有很好的辅助方法,可以让你的 sql 更具可读性和可维护性。

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

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

      【讨论】:

        猜你喜欢
        • 2017-02-07
        • 1970-01-01
        • 2015-02-23
        • 2018-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多