【问题标题】:Rails: `includes` a `has_many` relation with `limit`Rails:`includes`与`limit`的`has_many`关系
【发布时间】:2015-10-16 15:54:32
【问题描述】:

我正在使用 Rails 4.2。我有 3 个这样的表:

class Collection < ActiveRecord::Base
    has_many :shares
    has_many :images, through: :shares
    has_many :latest_images, -> { order(created_at: :desc).limit(10) }, class_name: 'Image', through: :shares, source: :image
end

class Share < ActiveRecord::Base
    belongs_to :image
    belongs_to :collection
end

class Image < ActiveRecord::Base
    has_many :shares
    has_many :collections, through: :shares
end

我的目标是选择一些收藏并使用latest_images 关系预加载每个收藏的前 10 张最新卡片。

如果我这样做:

collections = Collection.where(some_condition).includes(:latest_images)

问题是 latest_images 将包含所有卡片,而不仅仅是最后 10 个(即使有 limit(10)

collections.first.latest_images.count # => more than 10!!!

相反,如果我在加载集合后添加limit(10),则会出现 N+1 查询问题:

collections.each { |collection| collection.latest_images.limit(10).do_something } # N+1 QUERY

有什么办法吗?

【问题讨论】:

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


    【解决方案1】:

    associations documentation 中的“Eager loading of associations”下有一条注释:

    如果您使用指定的 :limit 选项急切加载关联,它将被忽略,并返回所有关联的对象。

    因此,尽管这可能不是直观的行为,但它的行为与记录的一样。

    解决方法是急切加载有限的关联并在之后单独访问。正如您指出的那样,这并不理想,但几乎可以肯定的是,无限制地加载所有关联的对象。

    【讨论】:

    • 所以没有办法在不加载所有内容并避免 N+1 查询的情况下急切加载该数据?
    • 不,我不认为不使用 arel 接口。我猜你可以编写自己的代码来完成它,但不幸的是你不会免费获得它。
    猜你喜欢
    • 2022-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多