活动记录中的多个查询

时间:2018-12-26 10:24:58

标签: ruby-on-rails ruby activerecord

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

NA
触发

多个查询(成员对象查询)(每个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 ,因为迭代器处于不同的条件。

4 个答案:

答案 0 :(得分:0)

根据您的代码,假设您拥有表名称为'profile_answers'表的模型Location

成员拥有许多profile_answers并通过profile_answers具有许多位置。

然后

members = Members.includes(profile_answers: :locations).where(id: ids)

答案 1 :(得分:0)

members是一个作用域。 members.find_by在范围内执行查询。因此是N+1

您想要的是:

members =
  Member.
    where(id: ids).
    includes(:locations).
    to_a # greedy load

puts members.map(&:location) # or whatever

答案 2 :(得分:0)

由于该行,您的代码将针对每个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

请注意,如果会员数很高,这会影响您的表现。

答案 3 :(得分:-1)

如果location是模型,则应使用include; includes将运行查询以获取您最初的model的数据和随附的模型

program = Program.first
ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
members = Members.includes(:locations).where(id: ids)

现在,当您获得第一个成员时,将从内存中读取其位置。

如果location是一列,并且您想加载所有成员,则可以执行以下操作:

program = Program.first
ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
members = Members.where(id: ids)
locations = members.pluck(:location)

最后,如果您不想使用成员,则可以执行以下操作:

program = Program.first
ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
locations = Members.where(id: ids).pluck(:location)