首页 > 解决方案 > 如何避免 Rails 4 中的 Eagerloading 问题

问题描述

下面是我的代码。

客户端在“事件”表中有许多带有外键 client_id 的事件

has_many :events

在控制台中

clients = Client.where(id: [110,112,113,115]).includes(:events)
=>  Client Load (0.4ms)  SELECT `clients`.* FROM `clients` WHERE `clients`.`id` IN (110, 112, 113, 115)
    Event Load (0.5ms)  SELECT `events`.* FROM `events` WHERE `events`.`client_id` IN (110, 112, 113, 115)

但是当跟随运行时,

clients.each { |cr| cr.events.count }
   (0.4ms)  SELECT COUNT(*) FROM `events` WHERE `events`.`client_id` = 110
   (0.3ms)  SELECT COUNT(*) FROM `events` WHERE `events`.`client_id` = 112
   (0.3ms)  SELECT COUNT(*) FROM `events` WHERE `events`.`client_id` = 113
   (0.3ms)  SELECT COUNT(*) FROM `events` WHERE `events`.`client_id` = 115

我收到 N+1 个查询,我遗漏了一些东西。

更新

从提供的答案中我得到了线索,我想要事件的 id,所以我正在尝试,

clients.each { |cr| cr.events.ids }
clients.each { |cr| cr.events.pluck(:id) }

所以 N+1 个查询被解雇了,然后我解决了以下问题,

clients.each { |cr| cr.events.map(&:id) }

我将 Relation 视为 Array 并使用maporidspluck解决了,没有 N+1 查询被触发。

标签: ruby-on-railsruby-on-rails-4activerecord

解决方案


如果您的目标是获取事件 ID,请使用 join with pluck

event_ids = Client.where(id: [110,112,113,115]).joins(:events).pluck('events.id')

推荐阅读