使用activerecord连接后计算对象

时间:2015-05-26 10:14:38

标签: ruby-on-rails activerecord rails-activerecord

我刚才注意到在.size的查询中使用.countjoins会产生意外结果。

User.some_scope.size #=> 10
User.joins(:associations).some_scope.size #=> 10 + associated object count

无论我加入桌面,如何获得符合范围的用户数量?

一些实际代码:

class User < ActiveRecord::Base
  has_many :tracking_logs, class_name: "Tracking::Log", dependent: :destroy
end

class Tracking::Log < ActiveRecord::Base
  belongs_to :user
end

User.where(created_at: Time.now-1.day..Time.now).size #=> 18
SQL: SELECT COUNT(*) FROM "users"  WHERE ("users"."created_at" BETWEEN '2015-05-25 10:40:11.423142' AND '2015-05-26 10:40:11.423741')
User.joins(:tracking_logs).where(created_at: Time.now-1.day..Time.now).size #=> 3188
SQL: SELECT COUNT(*) FROM "users" INNER JOIN "tracking_logs" ON "tracking_logs"."user_id" = "users"."id" WHERE ("users"."created_at" BETWEEN '2015-05-25 10:41:15.260113' AND '2015-05-26 10:41:15.260684')

我希望.size仅应用于我调用查询的基本模型,其他任何事情都只是令人困惑。

NB ,明确说明要检查哪个模型的created_at不会改变结果,例如

User.joins(:tracking_logs).where( users: { created_at: Time.now-1.day..Time.now } ).size #=> 3188
SQL: SELECT COUNT(*) FROM "users" INNER JOIN "tracking_logs" ON "tracking_logs"."user_id" = "users"."id" WHERE ("users"."created_at" BETWEEN '2015-05-25 10:49:29.485508' AND '2015-05-26 10:49:29.486120')

User attributes:
               :id => :integer,
         :category => :string,
            :email => :string,
       :created_at => :datetime,
       :updated_at => :datetime,
           :locale => :string,
   :original_email => :text,
  :registration_id => :integer,
       :first_name => :text,
      :login_count => :integer,
       :offer_type => :text,
              :cid => :string,
   :fb_like_status => :integer,
:product_purchases => :text

Tracking::Log attributes:
                  :id => :integer,
             :user_id => :integer,
 :tracking_referer_id => :integer,
                  :to => :string,
     :controller_name => :string,
         :action_name => :string,
:tracking_activity_id => :integer,
 :time_since_last_log => :integer,
          :created_at => :datetime,
          :updated_at => :datetime

1 个答案:

答案 0 :(得分:0)

此处的问题是,如果用户有多个跟踪日志,则联接将多次返回同一用户。您可以使用uniq仅为每个用户提供一次:

User.joins(:tracking_logs).where(created_at: Time.now-1.day..Time.now).uniq.size

另见:http://guides.rubyonrails.org/active_record_querying.html#joining-a-single-association