【问题标题】:How can I eager load and join on a condition for a polymorphic?我怎样才能急切地加载和加入多态的条件?
【发布时间】:2018-12-12 09:53:22
【问题描述】:

这是我的模型:

class Team < ApplicationRecord
  has_many :team_permissions
end

class TeamPermission < ApplicationRecord
  belongs_to :team
  belongs_to :permissible, polymorphic: true
end

class User < ApplicationRecord
  has_many :team_permissions, as: :permissible
end

我知道您可以通过以下方式解决您的 N+1 问题:

Team.includes(team_permissions: :permissible)

现在,我只想在一个条件下加入权限。例如,如果它们不属于一组 id,那么我希望这可以工作,但它会引发错误。

ActiveRecord:

Team.includes(team_permissions: :permissible).where.not(team_permissions: { id: team_permission_ids })

Error:

ActionView::Template::Error (Cannot eagerly load the polymorphic association :permissible):

进一步玩弄它,我发现以下方法按我想要的方式工作,但它不能解决 N+1 问题。

Team.includes(:team_permissions).where.not(team_permissions: { id: team_permission_ids })

我怎样才能在条件中包含对.includes 的预加载?

【问题讨论】:

    标签: ruby-on-rails activerecord ruby-on-rails-5 polymorphic-associations


    【解决方案1】:

    不幸的是,Active Record 不够聪明(老实说,也不够信任),无法计算出它需要加入第一个表才能应用您的条件,而不是第二个。

    你应该能够通过稍微明确一点来帮助它:

    Team.
      includes(:team_permissions).   # or eager_load(:team_permissions).
      preload(team_permissions: :permissible).
      where.not(team_permissions: { id: team_permission_ids }
    

    当没有条件引用includes 表时,默认行为是使用preload,它通过执行单个附加查询来处理N+1,并且与多态关联兼容。但是,当找到这样的条件时,all includes 将转换为 eager_load,这会在主查询中执行 LEFT JOIN(因此不兼容:不能编写一个查询加入我们甚至还不知道的表)。

    在上面,我已经将我们肯定要通过 preload 加载的部分分开,所以它应该做正确的事情。

    【讨论】:

      猜你喜欢
      • 2013-12-27
      • 1970-01-01
      • 2018-07-15
      • 2013-04-13
      • 2014-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多