【问题标题】:Override join generated by Rails eager_load覆盖 Rails eager_load 生成的连接
【发布时间】:2021-06-12 01:21:22
【问题描述】:

我有一种情况,我想对某些记录和eager_load 关联进行分组,所以我创建了一个类似这样的视图:

select group id, array_agg(order_ids) order_ids
from my_table
group by 1

所以它会有这样的记录:

id | order_ids
1  | {1, 2, 3}
2  | {4, 5}

然后我为这个视图创建了一个模型:

class MyGroup < ApplicationRecord
  scope :with_orders, -> {
    joins("JOIN orders on orders.id = any(order_ids)")
    .eager_load(orders: [:address, :products])
  }

  has_many :orders
end

问题是我找不到删除或覆盖 Rails 为 orders 关系生成的连接的方法,如下所示:

LEFT OUTER JOIN "orders" "orders_my_groups" ON "orders_my_groups"."my_group_id" = "my_groups"."id"

有没有办法告诉 Rails 使用特定的连接而不是 has_many 关联生成的连接?或者在这种情况下我可以使用任何其他类型的关联吗?

我在这里要做的是在单个查询中急切地加载组中的所有关联。

【问题讨论】:

    标签: ruby-on-rails rails-activerecord


    【解决方案1】:

    我放弃了尝试覆盖 Rails eager_load 生成的连接并使用了 has_many :through 关系:

    为分组写了一个这样的视图:

    SELECT group_id, description FROM my_table GROUP BY group_id
    

    并将其添加到使用此视图的模型中:

    class MyGroup < ApplicationRecord
      self.primary_key = "group_id"
    
      has_many :items, foreign_key: "group_id", class_name: "MyTable"
      has_many :orders, through: :items
    end
    

    现在 rails 只生成一个这样的 SQL 并且 eager_load 有效。

    SELECT group_id, description from my_view
    LEFT OUTER JOIN my_table ON my_table.group_id = my_group.group_id
    

    【讨论】:

      【解决方案2】:

      您不能覆盖 eager_load 连接。相反,您可以使用关联本身获取您正在寻找的数据。

      加载记录时立即加载

      @groups = MyGroup.includes(orders: [:address, :products])
      

      还有你需要order_ids的地方

      @groups.each do |group|
        # ...
        order_ids = group.order_ids # returns array object
      

      这里不需要再次使用join。会导致N+1。

      【讨论】:

      • 我不确定我是否理解您的建议。我尝试了它并加载了订单,但执行了 N+1,如果我使用 .joins(:orders) 我得到一个比较错误:ERROR: operator does not exist: bigint = bigint[]
      • 请分享您收到此错误的完整声明
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-16
      相关资源
      最近更新 更多