所以我有这些模特。
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。
答案 0 :(得分:0)
ForumTopic.unscoped.joins(:forum_topic_reads).where('user_id = ?', user[:id]).group(:id).having('forum_topic_reads.count < 1').pluck(:forum_id)