0

用户 ( has_many :user, has_many :comments) 发表 ( belongs_to :user, has_many :comments) 评论 ( belongs_to :user, belongs_to :post)

现在我正在尝试检索所有帖子(至少有一个用户的评论)更新了该帖子中用户最后评论的评论(我将为此使用用户的 updated_at 属性)

示例:帖子 A

用户 X,Y

X 在 A 中发表评论

然后 Y 在 A 中发表评论

现在我想检索帖子 A,因为在用户 X 的最后一条评论之后,在 A 中发布了一条新评论。

同样,我想检索在用户发表评论后发表评论的所有帖子。(updated_at每次他在任何帖子中发表评论时,我都会更新用户的价值)(我也更新updated_at了帖子的价值,每次 some1 在该帖子中发表评论)

我已经绞尽脑汁想如何在 RoR 中实现这一点,但没有得到任何线索,所以最后我求助于 StackOverflow :)

在此先感谢各位

4

2 回答 2

0

帕特里克有一些很好的建议。但我认为他误解了你的要求。当他的查询将帖子加入发布它们的用户时,而不是评论它们的用户。他走在正确的轨道上,而且他在索引方面绝对是正确的。

以下内容不起作用,因为您正在尝试获取评论对象上的帖子。

@post_ids = Comment.all(:select => "DISTINCT post_id",
  :conditions => ["user_id = ? AND updated_at > ?", 
  @userinfo.id, @userinfo.updated_at.to_date.to_time]) 

@posts = Post.find(@post_ids)

您可以将所有评论映射到帖子 ID。即:Post.find(@post_ids.map{&:post_id})但是需要两次数据库旅行并为命中实例化评论是低效的。

相反,您应该使用命名范围或其他东西来根据您的标准选择帖子。

class Post < ActiveRecord::Base
  ...
  #this is what you asked for.
  named_scope :with_unseen_comments_for_user, lamda do |user|
    {
     :select => "DISTINCT posts.*", :joins => "INNER JOIN comments, 
        comments others_comments, users ON (comments.user_id = users.id AND 
        others_comments.post_id = post.id AND comments.post_id = posts.id", 
      :conditions => ["users.id = ? AND 
        comments_posts.updated_at > users.updated_at", user]
    }
  end

end

#usage:
Post.updated_after_users_last_comment_in_post(@user)

需要复杂的连接语句来创建有效的查询,因为您希望连接工作列出以下内容:

其他评论 <--- post_id - id ---> 帖子 <--- id - post_id ---> 用户评论 <--- user_id - id ---> 用户

假设我的 SQL 是我记得的,这应该检索给定用户发表评论的所有帖子,并且他的最后一篇帖子是在其他人对同一帖子发表评论之前发表的。

无论如何,当用户在多个线程中发帖时,您会遇到问题。因此,您可能需要重新考虑您的关系并更新方法。

例如,如果发生以下情况,您的用户将不会收到关于帖子 A 的新评论的通知:

用户 X 对帖子 A 的评论

用户 Y 对帖子 A 的评论

用户 X 在注意到用户 Y 对帖子 A 发表评论之前评论了帖子 B。

您可以通过在评论中添加 last_seen_at 字段来解决此问题,并在所有者查看评论时更新它。这对于 :after_filter 来说相当简单。事实上,它使命名范围更简单。因为我们不需要将用户记录拖到查询中来比较日期。

  named_scope :unseen_comments, lamda do |user|
    {
     :select => "DISTINCT posts.*", :joins => [:comments, :comments], 
      :conditions => ["comments.user_id = ? AND 
        others_comments.updated_at > comments.last_seen_at", user]
    }
  end

:joins => [:comments, :comments]有点奇怪,但它会将评论加入查询中的帖子两次,第二次别名为comments_posts。它没有在 find 或 named_scope 中专门记录,但它使用与关联连接参数相同的语法。

于 2009-10-09T20:24:00.517 回答
0

SQL魔术:

class User
  def posts_with_comments_since_my_last_comment_in_that_post
     Post.find_by_sql([%Q| SELECT DISTINCT posts.* from posts INNER JOIN users on 
       (posts.user_id = users.id) INNER JOIN comments on 
       (comments.user_id = users.id AND comments.post_id = posts.id) 
       WHERE (posts.updated_at > comments.updated_at) AND (users.id = ?)|, id])
  end

  def posts_with_comments_since_my_last_comment
    Post.find_by_sql([%Q| SELECT DISTINCT posts.* from posts INNER JOIN users on 
         (posts.user_id = users.id) INNER JOIN comments on 
         (comments.user_id = users.id AND comments.post_id = posts.id) 
         WHERE (posts.updated_at > user.updated_at) AND (users.id = ?)|, id])
  end
end

您可以通过创造性地使用缓存来避免这种情况,但我不建议这样做。 确保您的表已正确编入索引。如果您运行一个有很多评论的网站, 这可能会非常非常错误。

于 2009-08-17T02:51:23.300 回答