我知道有关这些主题的问题很多,但我没有一个涵盖所有方面的问题。
考虑User
,Activity
和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_load
,includes
,includes & references
,includes & preload
(这些结果将导致左外部联接或单个额外查询)
这是我发现的问题:
order(created_at: :asc)
(参见rails issue)。它确实遵守显式排序,即default_scope { order(created_at: :asc) }
。.order("likes.created_at asc")
,希望限制单个额外的查询会破坏事情首选方法是仅查询所需记录的单个额外查询。总而言之,我找不到Rails的本地解决方案。有吗?
答案 0 :(得分:0)
在我的问题中,我正在寻找使用Rails的本地方法。但是,这是使用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)