【问题标题】:Rails - eager loading with has_many_through associationRails - 使用 has_many_through 关联进行急切加载
【发布时间】:2016-05-26 12:55:13
【问题描述】:

我有一个非常简单的 has_many_through 关联如下:

class Retailer < ActiveRecord::Base
  has_many :retailer_tags
  has_many :tags, through: :retailer_tags
end

class Tag < ActiveRecord::Base
  has_many :retailer_tags
  has_many :retailers, through: :retailer_tags
end

class RetailerTag < ActiveRecord::Base
  belongs_to :retailer
  belongs_to :tag
end

在我的零售商控制器的索引中,我想显示所有零售商及其相关标签的列表。如果我只是在我的控制器中有@retailers = Retailer.all,然后遍历我认为的所有零售商,我就会遇到 N+1 查询问题。

我可以直接使用 Postgresql 解决这个问题,它工作正常,但我想了解如何在 Rails 中解决。

当我执行@retailers = Retailer.eager_load(retailer_tags: :tag).all(或任何包含/预加载/连接)时,我仍然会收到 N+1 个查询。

我做错了什么? 谢谢你的帮助

【问题讨论】:

    标签: ruby-on-rails rails-activerecord


    【解决方案1】:

    @retailers = Retailer.eager_load(:tags).all或者你可以做:

    @retailers = Retailer.includes(:tag).all

    使用包含允许 Rails 根据情况进行最有效的查询。这将充当 eager_load 除非 LEFT_OUTER_JOIN 将返回错误,此时 Rails 将在 2 个查询中执行此操作,例如 preload

    【讨论】:

    • 工作得很好,谢谢,但我必须这样做:@retailers = Retailer.eager_load(:tags).all
    【解决方案2】:
    @retailers = Retailer.includes(:tag)
    

    【讨论】:

      【解决方案3】:

      rails 中有 3 种方法,使用它们可以预先加载关联,

      • 包括
      • 预加载
      • eager_load

      您的案例示例

      retaillers = Retailer.includes(:tag).all
      retaillers = Retailer.preload(:tag).all
      retaillers = Retailer.eager_load(:tag).all
      

      更多详情请见http://blog.arkency.com/2013/12/rails4-preloading/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        • 2015-10-16
        • 1970-01-01
        相关资源
        最近更新 更多