获取一个类别中所有帖子的最新评论

时间:2014-11-20 21:39:05

标签: ruby-on-rails postgresql ruby-on-rails-4 rails-activerecord postgresql-9.3

评论属于Post。
帖子属于Category。

我如何获得每篇帖子的最新更新评论的集合,这些评论都属于一个类别?

我试过这个,但它只给了我一个帖子:

category.posts.joins(:comments).order('updated_at DESC').first

更新

我想要的是每个帖子获取一个提交,每个帖子的最后更新评论。

4 个答案:

答案 0 :(得分:5)

Rails并没有做到这一点特别好,特别是Postgres禁止明显的解决方案(由@Jon和@Deefour提供)。

以下是我使用的解决方案,已转换为您的示例域名:

class Comment < ActiveRecord::Base
  scope :most_recent, -> { joins(
    "INNER JOIN (
      SELECT DISTINCT ON (post_id) post_id,id FROM comments ORDER BY post_id,updated_at DESC,id
    ) most_recent ON (most_recent.id=comments.id)"
  )}
  ...

DISTINCT ON是SQL标准的Postgres扩展,因此它不会在其他数据库上工作。)

简要说明:DISTINCT ON删除除post_id的第一行以外的所有行。它使用ORDER BY决定第一行是哪一行,post_id必须以updated at DESC开头,然后按id排序以获取最新版本,然后Comment.most_recent.joins(:post).where("posts.category_id" => category.id) 为打破平局(通常没必要)。

然后你会像这样使用它:

SELECT *
FROM comments
  INNER JOIN posts ON (posts.id=comments.post_id)
  INNER JOIN (
    SELECT DISTINCT ON (post_id) post_id,id FROM comments ORDER BY post_id,updated_at DESC,id
  ) most_recent ON (most_recent.id=comments.id)
WHERE
  posts.category_id=#{category.id}

它生成的查询类似于:

{{1}}

单一查询,非常高效。如果有人能给我一个不太复杂的解决方案,我会欣喜若狂!

答案 1 :(得分:1)

如果您想要收集每个上次更新的评论,您需要将查询基于Comment,而不是Category

Comment.joins(:post).
        where("posts.category_id = ?", category.id).
        group("posts.id").
        order("comments.updated_at desc")

答案 2 :(得分:1)

您基本上要求的是has_many :through协会。

尝试设置Category模型,如下所示:

class Category < ActiveRecord::Base
  has_many :posts
  has_many :comments, through: :posts
end

然后,您只需执行此操作即可获得最近10条更新的评论:

category.comments.order('updated_at DESC').limit(10)

您可以使用Comment模型上的命名范围使其更具可读性:

class Comment < ActiveRecord::Base
  scope :recently_updated, -> { order('updated_at DESC').limit(10) }
end

给你这个查询用于获得相同的10条评论:

category.comments.recently_updated

修改

所以,对于你真正想要的东西,一个类似的解决方案,但是它要求你从Comment结尾处理你的关联。

首先,在Comment上设置关联,以便了解其Category

class Comment < ActiveRecord::Base
  belongs_to :post
  has_one :category, through: :post
end

现在您可以像这样查询您的评论:

Comment.order('updated_at desc').joins(:post).where('posts.category' => category).group(:post_id)

有点啰嗦,但它确实有效。

答案 3 :(得分:0)

.first只抓一个给你。第一个准确。所以放弃.first。所以改为:

category.posts.joins(:comments).order('updated_at DESC')