优化ActiveRecord查询属性与where

时间:2015-12-29 03:44:45

标签: sql ruby-on-rails performance activerecord

我有一个包含这两种方法的模型project_leadproject_operative_lead

当我尝试获取这两个属性时,我得到了大量的查询。即使我试图使用包含。

这是我的模特:

class Project < ActiveRecord::Base
  has_many :project_sales_contributions, dependent: :destroy
  has_many :sales_contributors, through: :project_sales_contributions, source: 'employee'

  has_many :project_contributions,  dependent: :destroy
  has_many :contributors, through: :project_contributions, source: 'employee'

  accepts_nested_attributes_for :project_customer_contacts,
    :project_contributions,
    :project_sales_contributions,
    allow_destroy: true,
    reject_if: :all_blank

  def project_lead
    project_contributions.where(role: 'lead').map { |e| e.employee.name }
  end

  def project_operative_lead
    project_contributions.where(role: 'operative_lead').map { |e| e.employee.name }
  end

end

这是我的包含声明: Project.includes(:customer, project_contributions: [ :employee ]).all

但是我仍然会收到n + 1个查询。

有什么方法可以减少查询次数吗?

2 个答案:

答案 0 :(得分:6)

where子句作用于ActiveRecord对象。 project_contributionsEnumerable,因此您可以对其进行迭代方法,例如mapselect等。无需再次查询该表以获得所需内容。

顺便说一下为什么不在这里使用joins呢?您可以使用joins代替include。使用includes时,您急切地加载了customer模型,因为您没有使用Customer模型的属性,因此您的情况有点过分。只是我的两分钱。

Project.joins(:customer, project_contributions: [ :employee ]).all

答案 1 :(得分:0)

您再次查询project_contributions以打破包含,您可以尝试选择:

project_contributions.select{ |e| e.role == 'lead' }.map{ |e| e.employee.name }