gpt4 book ai didi

ruby-on-rails - rails : how to eager load limited records of ordered association without N+1 queries

转载 作者:数据小太阳 更新时间:2023-10-29 07:19:39 26 4
gpt4 key购买 nike

我知道关于其中一些主题有很多问题,但我没有找到涵盖所有方面的问题。

考虑UserActivityLike 模型。当我查询一个事件时,我想为集合中的每个事件加载第一个 Like 而不进行 N+1 查询并且不加载超过必要的记录。我的代码看起来像这样:

class User < ActiveRecord::Base
has_many :likes, as: :liker
end

class Activity < ActiveRecord::Base
has_many :likes
has_one :first_like, -> { order(created_at: :asc) }, class_name: "Like"
end

class Like < ActiveRecord::Base
belongs_to :activity
belongs_to :liker, polymorphic: true
end

我做了一个全面的要点来测试不同的加载策略和方法:https://gist.github.com/thisismydesign/b08ba0ee3c1862ef87effe0e25386267

策略:N+1查询、左外连接、单次额外查询

方法:eager_loadincludesincludes & referencesincludes & preload(这些将导致左外连接或单个额外查询)

这是我发现的问题:

  • 左外连接不遵守关联范围内的 order(created_at: :asc) 也不遵守 default_scope { order(created_at: :asc) }(参见:rails issue ).它确实尊重显式排序,即 .order("likes.created_at asc")
  • 但仍应避免左外连接,因为它“可能导致许多行包含冗余数据,并且在规模上表现不佳”(请参阅​​:apidoc rubydocrails api)。对于大量数据,即使双方都进行索引搜索,这也是一个真正的问题。
  • 单个额外查询将创建一个无限制的查询,可能会获取大量数据(参见:rails issue)
  • 向关联添加显式 limit(1) 希望限制单个额外查询会破坏事情

首选方法是仅查询所需记录的单个额外查询。总而言之,我无法找到 Rails 的原生解决方案。有吗?

最佳答案

在我的问题中,我正在寻找使用 Rails 的 native 方式。但是,这里有一个使用 SQL 和虚拟属性的解决方案:

class Activity < ApplicationRecord
has_one :first_like, class_name: "Like", primary_key: :first_like_id, foreign_key: :id

scope :with_first_like, lambda {
select(
"activities.*,
(
SELECT like_id as first_like_id
FROM likes
WHERE activity_id = activities.id
ORDER BY created_at ASC
LIMIT 1
)"
)
}
end

Activity.with_first_like.includes(:first_like)

关于ruby-on-rails - rails : how to eager load limited records of ordered association without N+1 queries,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56565472/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com