我有这个方法。它的工作是返回一份已经毕业于开发商的学员名单。用户筛选他们在开发人员中寻找的技能。返回列表时,列表的顶部是更相关的开发人员。
这是控制器方法:
def filter
@skills = Skill.all
@developers = []
unless params[:ids].nil?
params[:ids].each do |skill|
skill = @skills.find(skill)
skill.trainees.each do |developer|
@developers << developer
end
end
end
if @developers.empty?
@developers = Trainee.developers.all
else
@developers = @developers.group_by {|x| x}.map {|k, v| [k, v.count]}
@developers.sort_by!(&:last).reverse!
@developers.map! do |developer|
developer[0]
end
end
respond_to do |format|
format.js {}
end
end目前,相同的方法正在按我想要的次数访问服务器。下面的服务器日志显示的结果是我单击了11个要过滤的按钮。可以是1、5或20,这取决于用户所寻找的内容。
Processing by SkillsController#filter as */*
Parameters: {"ids"=>["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"]}
Skill Load (0.6ms) SELECT `skills`.* FROM `skills` WHERE `skills`.`id` = 1 LIMIT 1
Trainee Load (0.6ms) SELECT `trainees`.* FROM `trainees` INNER JOIN `mastered_skills` ON `trainees`.`id` = `mastered_skills`.`trainee_id` WHERE `mastered_skills`.`skill_id` = 1
Skill Load (0.4ms) SELECT `skills`.* FROM `skills` WHERE `skills`.`id` = 2 LIMIT 1
Trainee Load (0.6ms) SELECT `trainees`.* FROM `trainees` INNER JOIN `mastered_skills` ON `trainees`.`id` = `mastered_skills`.`trainee_id` WHERE `mastered_skills`.`skill_id` = 2
Skill Load (0.3ms) SELECT `skills`.* FROM `skills` WHERE `skills`.`id` = 3 LIMIT 1
Trainee Load (1.3ms) SELECT `trainees`.* FROM `trainees` INNER JOIN `mastered_skills` ON `trainees`.`id` = `mastered_skills`.`trainee_id` WHERE `mastered_skills`.`skill_id` = 3
Skill Load (6.1ms) SELECT `skills`.* FROM `skills` WHERE `skills`.`id` = 4 LIMIT 1
Trainee Load (0.6ms) SELECT `trainees`.* FROM `trainees` INNER JOIN `mastered_skills` ON `trainees`.`id` = `mastered_skills`.`trainee_id` WHERE `mastered_skills`.`skill_id` = 4
Skill Load (0.3ms) SELECT `skills`.* FROM `skills` WHERE `skills`.`id` = 5 LIMIT 1
Trainee Load (0.9ms) SELECT `trainees`.* FROM `trainees` INNER JOIN `mastered_skills` ON `trainees`.`id` = `mastered_skills`.`trainee_id` WHERE `mastered_skills`.`skill_id` = 5
Skill Load (2.6ms) SELECT `skills`.* FROM `skills` WHERE `skills`.`id` = 6 LIMIT 1
Trainee Load (2.0ms) SELECT `trainees`.* FROM `trainees` INNER JOIN `mastered_skills` ON `trainees`.`id` = `mastered_skills`.`trainee_id` WHERE `mastered_skills`.`skill_id` = 6
Skill Load (4.2ms) SELECT `skills`.* FROM `skills` WHERE `skills`.`id` = 7 LIMIT 1
Trainee Load (0.9ms) SELECT `trainees`.* FROM `trainees` INNER JOIN `mastered_skills` ON `trainees`.`id` = `mastered_skills`.`trainee_id` WHERE `mastered_skills`.`skill_id` = 7
Skill Load (1.2ms) SELECT `skills`.* FROM `skills` WHERE `skills`.`id` = 8 LIMIT 1
Trainee Load (3.0ms) SELECT `trainees`.* FROM `trainees` INNER JOIN `mastered_skills` ON `trainees`.`id` = `mastered_skills`.`trainee_id` WHERE `mastered_skills`.`skill_id` = 8
Skill Load (0.3ms) SELECT `skills`.* FROM `skills` WHERE `skills`.`id` = 9 LIMIT 1
Trainee Load (0.8ms) SELECT `trainees`.* FROM `trainees` INNER JOIN `mastered_skills` ON `trainees`.`id` = `mastered_skills`.`trainee_id` WHERE `mastered_skills`.`skill_id` = 9
Skill Load (2.1ms) SELECT `skills`.* FROM `skills` WHERE `skills`.`id` = 10 LIMIT 1
Trainee Load (0.6ms) SELECT `trainees`.* FROM `trainees` INNER JOIN `mastered_skills` ON `trainees`.`id` = `mastered_skills`.`trainee_id` WHERE `mastered_skills`.`skill_id` = 10
Skill Load (0.3ms) SELECT `skills`.* FROM `skills` WHERE `skills`.`id` = 11 LIMIT 1
Trainee Load (0.8ms) SELECT `trainees`.* FROM `trainees` INNER JOIN `mastered_skills` ON `trainees`.`id` = `mastered_skills`.`trainee_id` WHERE `mastered_skills`.`skill_id` = 11
Rendering skills/filter.js.haml
Skill Load (0.7ms) SELECT `skills`.* FROM `skills` INNER JOIN `mastered_skills` ON `skills`.`id` = `mastered_skills`.`skill_id` WHERE `mastered_skills`.`trainee_id` = 5
Skill Load (0.5ms) SELECT `skills`.* FROM `skills` INNER JOIN `mastered_skills` ON `skills`.`id` = `mastered_skills`.`skill_id` WHERE `mastered_skills`.`trainee_id` = 2728
Skill Load (0.6ms) SELECT `skills`.* FROM `skills` INNER JOIN `mastered_skills` ON `skills`.`id` = `mastered_skills`.`skill_id` WHERE `mastered_skills`.`trainee_id` = 10发布于 2017-03-24 05:26:53
首先,@skills可以定义为:@skills = params[:ids].nil? ? Skill.all : Skills.where(id: params[:ids])
然后你就面临着n+1问题。为了避免这种情况,您必须使用殷切装载协会 (ELA)或联接。
若要返回带ELA的受训者对象,可以使用map和flatten。
接下来,你有一个很好的角色:
@developers = @developers.group_by {|x| x}.map {|k, v| [k, v.count]}
@developers.sort_by!(&:last).reverse!sort_by(&:last).reverse工作得很快。
本部分:
@developers.map! do |developer|
developer[0]
end可改为:
@developers.map(&:first)并与以前的sort_by联合
@developers = @developers.sort_by(&:last).reverse.map(&:first)希望能帮上忙。
发布于 2017-03-23 12:40:18
优化本部分:
@skills = Skill.all
@developers = []
unless params[:ids].nil?
params[:ids].each do |skill|
skill = @skills.find(skill)
skill.trainees.each do |developer|
@developers << developer
end
end
end至:
@developers = Skill.where(id: params[:ids]).joins(:trainees).select('trainees.*')发布于 2017-03-23 12:38:07
所描述的问题看起来像一个N+1 problem。急切地加载关联可能会有所帮助:Querying.html#急切-加载-关联
https://stackoverflow.com/questions/42976117
复制相似问题