【问题标题】:Eager loading with has_many through通过 has_many 进行热切加载
【发布时间】:2014-05-04 18:28:31
【问题描述】:

我有一个User 模型。

一个user 有很多integrations

integration 通过包含data 列的integration_profiles 连接到profile

我想立即加载所有用户的个人资料。

class Integration < ActiveRecord::Base
 has_many :integration_profiles
 has_many :profiles, through: :integration_profiles
end

class IntegrationProfile < ActiveRecord::Base
 belongs_to :integration
 belongs_to :profile
end

class Profile < ActiveRecord::Base
 has_many :integration_profiles
 has_many :integrations, through: :integration_profiles
end

我试过这个:

all = User.first.integrations.includes(:profiles)

但我当我all.count

=> 2

但是当我这样做时

all = User.first.integrations.joins(:profiles)
all.count
=> the correct total

我应该使用包含还是连接?我一直使用包含,所以不知道为什么这在这里不起作用

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-4 eager-loading


    【解决方案1】:

    当你这样做时

    all = User.first.integrations.joins(:profiles)
    all.count
    

    将针对第一个 User 计算集成记录,并对 profiles 进行内部连接查询。

    当你这样做时

    all = User.first.integrations.includes(:profiles)
    all.count
    

    您再次获得集成计数,但没有使用配置文件连接查询,因为配置文件急切加载了单独的查询,因为 includes

    您似乎只想将profiles 计数关联到给定的user。实现这一点的最佳方法是在 UserProfile 模型之间创建关联

    User ==&gt; has_many :profiles, through: :integration

    完成此操作后,您可以直接访问 User.first.profiles.count 以获取特定用户的所有关联配置文件的计数。

    另一个选项是(如果您不想使用上述选项)循环遍历所有 integrations 并为每个集成总结所有 profiles.count

    选择最适合您需求的选项。

    【讨论】:

    • 嗨@KirtiThorat,我如何能够向后调用或选择连接集成和配置文件的联合模型?
    【解决方案2】:

    查询 1

    all = User.first.integrations.includes(:profiles)

    all.count 正在返回集成计数,而不是配置文件。配置文件被急切地加载。

    如果您想知道配置文件的数量,则需要以这种方式完成。

    ar = [ ]
    
     all.each do |a|
       ar << a.profiles.count
     end
    

    ar.reduce(:+) 将在您运行查询 2 时为您提供相同的计数。

    查询 2

    all = User.first.integrations.joins(:profiles)

    all.count

    在查询 2 的情况下,它会从 integrartion_profiles 表返回您的集成。

    Select users from users limit 1;

    Select integrations from integrations INNER JOIN integration_profiles on integration_profiles.integration_id = integrations.id where integrations.user_id = 'id of user'

    要了解更多信息,请在查询 1 和查询 2 上调用 .to_sql。

    如果您想进行即时加载,那么使用包含是首选选项。

    【讨论】:

    • 好的,我想进行预加载,这样我就可以调用User.first.profiles,我该如何进行预加载?
    猜你喜欢
    • 2015-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    • 2020-10-15
    相关资源
    最近更新 更多