查找新论坛帖子的棘手问题

时间:2015-08-19 19:37:09

标签: sql ruby-on-rails forum

所以我有这些模特。

class Forum < ActiveRecord::Base
  has_ancestry
  has_many :forum_topics
end

class ForumTopic < ActiveRecord::Base
  belongs_to :forum
  has_many :forum_topic_reads

  # has a :last_post_at date column 
end

class ForumTopicRead < ActiveRecord::Base
  belongs_to :forum_topic
  belongs_to :user

  # has a :updated_at date column
end

非常基本的设置。

现在我想得到的是一些论坛的ID,这些论坛在他们的子树中有未读的帖子。新帖子的存在取决于forum_topics.last_post_at与forum_topic_reads.updated_at的比较,其中forum_topics.id = forum_topic_reads.forum_topic_id用于特定的user_id,或者当该主题和用户缺少ForumTopicRead记录时。

问题是 - 我设法使其工作的唯一方法是手动浏览每个论坛并制作其子树,然后获取子树的所有主题等。这导致对数据库的大量类似查询和这是一个非常缓慢的过程。

我相信应该有办法让它变得更快。我只需要在他们的子树中至少有一个未读主题的论坛的ID,不需要计数,不需要自己的主题ID。

更新

得到了@MrYoshiji的提示

此查询:

ForumTopic.joins(:forum_topic_reads).where('forum_topics.last_post_at > forum_topic_reads.updated_at AND forum_topic_reads.user_id = ?', user.id).pluck(:forum_id).uniq

效果不好,因为它忽略了适当的topic_reads主题(并为每个用户创建每个主题的读取都有点开销)

更新2

所以我终于找到了一条崭露头角的道路。如果我在添加新帖子时删除主题的所有读取(从而更新:last_post_at字段),我将能够使用此查询收集forum_ids

"SELECT distinct forum_id FROM `forum_topics` LEFT JOIN forum_topic_reads ON forum_topic_reads.forum_topic_id = forum_topics.id AND forum_topic_reads.user_id = #{user.id} GROUP BY forum_topics.id  having count(forum_topic_reads.id) < 1"

现在我遇到的唯一大问题是将其从SQL转换为ActiveRecord。

1 个答案:

答案 0 :(得分:0)

 ForumTopic.unscoped.joins(:forum_topic_reads).where('user_id = ?', user[:id]).group(:id).having('forum_topic_reads.count < 1').pluck(:forum_id)