如果我在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
,因为迭代器处于不同的条件。
答案 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)