【问题标题】:ActiveRecord format joins into an arrayActiveRecord 格式加入数组
【发布时间】:2020-05-17 07:58:21
【问题描述】:

我想提高我的一个端点的效率。这是纲要:

在一个 mysql 数据库中,我们有三个示例表,其中两个是第一个的连接表。

:user has_many: :orders 
:user has_many: :attributes

后续查询很简单(但可能会发生变化):

User.left_joins(:orders, :attributes).select("users.*, orders.*, attributes.*")

此查询返回大对象,对于每个用户、存在的订单或属性,它返回一个平面对象。

[
  {
    User:
     id: 1,
     order_id: 1,
     order_columns_here,
     attribute_id: 1,
     attribute_columns_here
  },
  {
    User:
     id: 1,
     order_id: 2,
     order_columns_here,
     attribute_id: 2,
     attribute_columns_here
  }
]

结果是一个相同用户数据的数组,每个订单或与其关联的属性重复多次。

如果我必须编写一些 ruby​​ 来按照 API 请求的方式格式化这个对象,它会很慢(我们有一个巨大的数据库)。是否有一种活动记录方法可用于扩充此查询,以便返回数据以及数组中的所有照片和 floor_plans?

[
  {
    User: id: 1, orders: [all_order_data_for_user_1], attributes: [all_attributes_data_for_user_1]
  }
]

在过去的几年里,我一直在使用 Sequel gem,它为我做到了这一点。我已经阅读了很多 AR 文档,但不确定 ActiveRecord 世界对我有什么帮助。

有什么想法吗?

编辑

mysql版本:mysql Ver 14.14 Distrib 5.7.29 导轨:5 红宝石:2.3.1

【问题讨论】:

  • 你打算如何使用结果?您可以使用.includes 代替.left_joins,它会预加载关系。

标签: mysql ruby activerecord ruby-on-rails-5


【解决方案1】:

如果您事先知道您将使用这两个关联,则可以使用.eager_load,它将在一个查询中加载所有关联的项目:

User.eager_load(:orders, :attributes)

如果你不太清楚,你可以使用它优柔寡断的双胞胎.includes,它试图变得聪明,可以根据其使用方式、风向和月相创建一个两个查询。

这使您可以遍历记录并调用关联,而无需创建 n+1 查询:

User.eager_load(:orders, :attributes).each |user|
  puts user.order.inspect
end

但您通常会将数据传递给序列化程序或 jbuilder 模板进行格式化。

见:Preload, Eagerload, Includes and Joins

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    • 2021-05-13
    • 2013-01-19
    • 1970-01-01
    相关资源
    最近更新 更多