使用has_many关联的Rails N + 1查询

时间:2016-09-21 06:34:15

标签: ruby-on-rails ruby

模型关系是

section has_many :sections
section belong_to :section
section has_many :questions
question_set has_many :questions, :through => :question_sets_questions

我遇到N + 1查询问题,但我不知道该怎么弄清楚。

这是代码

def test
  question_set_id = params[:qset_id].to_i
  q_ids = QuestionSetsQuestion.where(:question_set_id => question_set_id).pluck(:question_id)
  questions = Question.where(:id => q_ids).includes(:section)
  questions.each do |q|
    section = {id: q.section.id, name: q.section.name}
    parent_section = q.section.section rescue nil
    p parent_section.id
  end
end

bullet宝石说

N+1 Query detected
  Section => [:section]
  Add to your finder: :include => [:section]
N+1 Query method call stack

我是否错误地提出了includes

更新

谢谢@Deepak,.includes(section: :section)可以解决两层部分。但实际上我有三个层次的部分。原始代码看起来像

questions.each do |q|
  section = {id: q.section.id, name: q.section.name}
  parent_section = q.section.section rescue nil
  while parent_section.present?
    section = {id: parent_section.id, name: parent_section.name, children: [section]}
    parent_section = parent_section.section rescue nil
  end
  p section 
end

2 个答案:

答案 0 :(得分:1)

首先,协会真的令人困惑。

我认为您正在调用两个问题的层次结构,因此更改此行应该可以正常工作

questions = Question.where(:id => q_ids).includes(section: :section)

您正在访问q.section的父部分,因此我们也需要包含该部分

parent_section = q.section.section rescue nil

修改

它越来越混乱我不确定你是否应该这样做,但我认为这将解决问题

questions = Question.where(:id => q_ids).includes(section: [section: :section])

答案 1 :(得分:0)

而不是这段代码:

  questions.each do |q|
    section = {id: q.section.id, name: q.section.name}
    parent_section = q.section.section rescue nil
    p parent_section.id
  end

放置一个查询并迭代其

parent_sections = Section.joins(sections: :questions).where(questions: {id:  questions.pluck(:id)})
parent_sections.each { |section| p section.id }