如何将 eager_load 和 select 一起使用?

问题描述 投票:0回答:3

我尝试使用

eager_load
仅选择某些列,但我面临着它取消我的“选择”的问题。

型号:

class Timeline < ActiveRecord::Base
    belongs_to :timeline_category, foreign_key: :timeline_category_id
    belongs_to :user, foreign_key: :user_id
    scope :with_relations, -> { eager_load(:timeline_category).eager_load(:user).order(created_at: :desc) 
end

查询:

Timeline.select('timelines.*, users.username, timeline_categories.icon').eager_load(:timeline_category).eager_load(:user)

我也尝试过:

Timeline.select('timelines.*, users.username, timeline_categories.icon').with_relations

由于某种原因,它不断选择所有 3 个表的所有列。我该如何解决它?

ruby-on-rails eager-loading
3个回答
6
投票

Rails 5 引入了 left_outer_joins 方法。所以终于可以了:

Timeline.left_outer_joins(:timeline_category, :user)
        .select('timelines.*, users.username, timeline_categories.icon')

1
投票

长期以来一直想要一种方法来修剪 #includes 和 #eager_load 的 SELECT 列表。今天终于坐下来弄清楚了,它已经作为我维护的数据相关宝石的一部分发布了,The Brick

通过像这样覆盖

ActiveRecord::Associations::JoinDependency.apply_column_aliases()
,然后当您添加
.select(...)
时,它可以充当过滤器来选择构建哪些列别名。

加载

gem 'brick'
后,为了启用此选择性行为,请将特殊列名称
:_brick_eager_load
添加为
.select(...)
中的第一个条目,这会在构建别名时打开列过滤。这是一个例子:

Employee.includes(orders: :order_details)
        .references(orders: :order_details)
        .select(:_brick_eager_load,
                'employees.first_name', 'orders.order_date', 'order_details.product_id')

由于外键对于正确关联所有内容至关重要,因此它们会自动添加,因此您无需将它们包含在选择列表中。

欢迎对此方法提供任何反馈——希望它可以节省您的查询时间和一些 RAM!


0
投票

我不确定这是否可能,但你可以这样做:

relation = TimeLine.joins(:timeline_category, :user).select('users.username AS username, timeline_categories.icon AS categories_icon')

然后使用

relation.each{ |timeline| puts "username: #{timeline.username} and icon: #{timeline.categories_icon}" }

获取这些字段
© www.soinside.com 2019 - 2024. All rights reserved.