【问题标题】:Count number of commenters统计评论人数
【发布时间】:2015-02-06 08:38:33
【问题描述】:

有文章和评论。

class Comment < ActiveRecord::Base
  belongs_to :user
  belongs_to :article, counter_cache: true
end

您可以通过执行以下操作来计算评论数量: @article.cmets_count

问题是 - 您如何计算对特定 @article 发表评论的唯一用户数量? (注意:一个唯一的用户可以留下多个cmets)

这是一个场景:

  1. 评论 - user_id(1)
  2. 评论 - user_id(4)
  3. 评论 - user_id(1)

cmets 计数 = 3
评论者(发表评论的唯一用户)计数 = 2

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4


    【解决方案1】:

    Rails 有很棒的 distinct query method,这使得这个特定的查询很容易生成:

    Comment.where(article_id: article.id).select(:user_id).distinct.count
    

    生成以下 SQL:

    SELECT DISTINCT COUNT(DISTINCT "comments"."user_id") FROM "comments" WHERE "comments"."article_id" = ?
    

    这种方法的好处是您可以让数据库完成繁重的工作。数据库通常比直接在 Ruby 中操作对象快几个数量级。

    如果你愿意修改你的Article 类如下:

    class Article < ActiveRecord::Base
      has_many :comments
      has_many :commenters, through: :comments, source: :user
      has_many :unique_commenters, -> { distinct }, through: :comments, source: :user
    end
    

    您还可以使用以下代码生成查询:

    article.unique_commenters
    

    生成以下 SQL:

    SELECT DISTINCT "users".* FROM "users" INNER JOIN "comments" ON "users"."id" = "comments"."user_id" WHERE "comments"."article_id" = ?
    

    【讨论】:

      【解决方案2】:

      尝试使用pluckuniq

      @article.comments.uniq.pluck(:user_id)

      或者只是pluck

      @article.comments.pluck("DISTINCT user_id")

      【讨论】:

        【解决方案3】:
        article.comments.collect(&:user).uniq{|user| user.id}.count
        

        【讨论】:

          【解决方案4】:

          您可以为此使用 Ruby 的 Set

          unique_commenters = Set.new
          
          comments.each do |comment|
            unique_commenters.add comment.user
          end
          
          unique_commenters.to_a
          

          您也可以只对集合执行 commenters.uniq!,但我想这样效率较低。

          【讨论】:

            【解决方案5】:

            我知道的最好的方法是创建一个范围:

            class Comment
              belongs_to :user
              belongs_to :article, counter_cache: true  
            
              scope :count_by_user ->(user) { where(user_id: user.id).count }
            end
            

            然后:

            @article.comments.count_by_user(user) # 2
            

            【讨论】:

              猜你喜欢
              • 2014-05-14
              • 2011-08-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-11-13
              • 1970-01-01
              • 1970-01-01
              • 2011-03-21
              相关资源
              最近更新 更多