两个多对多连接模型的Active Record查询优化

时间:2016-06-06 01:24:46

标签: ruby-on-rails postgresql activerecord

我在使用ActiveRecord和Postgres SQL的Rails 4中显示产品模型的下表:

enter image description here

这是我的ERD,我使用了几个多对多模型,这里的每个箭头代表一对多的关系:

enter image description here

  • impact_line_items是行标题(" Total Impacts"," Source" ......等)。
  • 类别是列标题("温室气体","能源消耗" ......等)
  • 通过向impact_line_items和类别添加条目,我基本上可以扩展表格的行和列
  • product_impact_line_item表示对一行数据的引用
  • impact_entry表示数据的单元格

问题:以下是我在modesl和products / show.html.erb中显示的内容。它正在进行35次查询以获取每个ImpactEntry,并需要一段时间才能加载。我想优化它并寻找建议。

型号:

class Product < ActiveRecord::Base
  ...
  has_many :product_impact_line_items, dependent: :destroy
  has_many :impact_line_items, through: :product_impact_line_items
  ...
end

class ProductImpactLineItem < ActiveRecord::Base
  belongs_to :product
  belongs_to :impact_line_item

  has_many :impact_entries, dependent: :destroy
  has_many :categories, through: :impact_entries

  def find_impact_entry(category)
    impact_entries.find_by_category_id(category.id)
  end

end

class ImpactEntry < ActiveRecord::Base
  belongs_to :product_impact_line_item
  belongs_to :category

end

class ImpactLineItem < ActiveRecord::Base
  has_many :product_impact_line_items, dependent: :destroy
  has_many :products, through: :product_impact_line_items

  validates :name, uniqueness: true

end

class Category < ActiveRecord::Base
  has_many :impact_entries, dependent: :destroy
  has_many :categories, through: :impact_entries
  validates :name, uniqueness: true
end

查看:

<table id="impacts-table" class="table table-bordered table-medium">
  <thead>
    <tr>
      <th class="col-md-2"></th>
      <% Category.all.each do |category| %>
          <th class="col-md-2"><%= category.name %></th>        
      <% end %>
    </tr>

  </thead>

  <tbody>
    <% product_impact_line_items = @product.product_impact_line_items %>
    <% product_impact_line_items.all.each do |product_impact_line_item| %>
        <tr>
          <th scope="row"><%= product_impact_line_item.impact_line_item.name %></th>
           <% Category.all.each do |category| %>
               <%# byebug %>
               <td class="col-md-2"> <%= product_impact_line_item.find_impact_entry(category).value %></td>
           <% end %>
        </tr>

    <% end %>

 </tbody>
</table>

1 个答案:

答案 0 :(得分:1)

  1. 使用ProductImpactLineItem.includes(:impact_line_item, :impact_entries)代替ProductImpactLineItem.allhttp://apidock.com/rails/ActiveRecord/QueryMethods/includes
  2. impact_entries.find_by_category_id(category.id)更改为impact_entries.find{ |ie| ie.category_id == category.id },以便每次都不会调用数据库
  3. 使用bullet gem检测以后的n + 1个查询
相关问题