首页 > 解决方案 > 活动记录中的多个查询

问题描述

如果我在 Rails 控制台中运行此查询,

def c
  ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  users = User.all
  members = Member.where(id: ids).includes(:locations)
  user_id_to_member_id_mapping = {} # Not empty. hash that gives member_id for each userid  
  users.each do |user|
    puts members.find_by(id: user_id_to_member_id_mapping[user.id]).location
  end
end

触发多个查询(成员对象查询)(每个值一个i)。成员是否已经在内存中(members变量)?如何获取上述进行单个查询所需的数据?

Member Load (0.2ms)  SELECT  `members`.* FROM `members` WHERE `members`.`id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) AND `members`.`id` = 1 LIMIT 1
  ProfileAnswer Load (0.4ms)  SELECT `profile_answers`.* FROM `profile_answers` WHERE `profile_answers`.`member_id` = 1
  Member Load (0.4ms)  SELECT  `members`.* FROM `members` WHERE `members`.`id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) AND `members`.`id` = 2 LIMIT 1
  ProfileAnswer Load (0.2ms)  SELECT `profile_answers`.* FROM `profile_answers` WHERE `profile_answers`.`member_id` = 2
  Member Load (0.2ms)  SELECT  `members`.* FROM `members` WHERE `members`.`id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) AND `members`.`id` = 3 LIMIT 1
  ProfileAnswer Load (0.2ms)  SELECT `profile_answers`.* FROM `profile_answers` WHERE `profile_answers`.`member_id` = 3
  Member Load (0.2ms)  SELECT  `members`.* FROM `members` WHERE `members`.`id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) AND `members`.`id` = 4 LIMIT 1
  ProfileAnswer Load (0.2ms)  SELECT `profile_answers`.* FROM `profile_answers` WHERE `profile_answers`.`member_id` = 4
  Member Load (0.2ms)  SELECT  `members`.* FROM `members` WHERE `members`.`id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) AND `members`.`id` = 5 LIMIT 1
  ProfileAnswer Load (0.2ms)  SELECT `profile_answers`.* FROM `profile_answers` WHERE `profile_answers`.`member_id` = 5
  Member Load (0.4ms)  SELECT  `members`.* FROM `members` WHERE `members`.`id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) AND `members`.`id` = 6 LIMIT 1

我不能使用member.each,因为迭代器处于不同的条件。

标签: ruby-on-railsrubyactiverecord

解决方案


Member由于该行,您的代码将为每个负载触发一个查询

members.find_by(id: ids[i]).location

在这里,您已经明确使用find_by了为每个成员触发查询的位置。

如果减少查询是优先事项,那么您可以在此处使用 ruby

def c
  ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  users = User.all
  members = Member.where(id: ids).includes(:locations)
  user_id_to_member_id_mapping = {} # Not empty. hash that gives member_id for each userid  
  users.each do |user|
   puts members.find { |m| m.id == user_id_to_member_id_mapping[user.id] }&.location
end

请注意,如果会员数量非常多,这会影响您的表现。


推荐阅读