Rails数据库查询ROR

时间:2017-03-25 21:07:04

标签: ruby-on-rails ruby database ruby-on-rails-4 rails-activerecord

首先,我还是ROR的新手,我正在努力想出更有效的方法来为我的数据表进行数据库查询。

我的模特协会

class Store < ActiveRecord::Base
  has_many :surveys
  has_many :customers 
end
...
class Survey < ActiveRecord::Base
  belongs_to :store
end
...
class Customer < ActiveRecord::Base
  belongs_to :store
end

在我的DataTables中

          <tbody>
            <% @store.surveys.each do |survey| %>
            <tr class="th-container table-fixer">
              <td><%= find_customer_id(survey.email).nil? ? survey.first_name : link_to(survey.first_name, store_customer_path(@store, find_customer_id(survey.email))) %></td>
              <td><%= get_ltv(survey) %></td>         
            </tr>
            <% end %>
          </tbody>

find_customer_id和get_ltv方法如下

def find_customer_id(customer_email)
   BwCustomer.find_by(email: customer_email)
end

代码的问题在于,目前我有超过1000个活动记录对象,当我查看find_customer_id方法时,它会找到具有给定电子邮件地址的客户,并且查询需要15秒才能处理。

在我看来,最好的办法是什么?

我有解决方案:   1.加入表格,以便我不必再调用另一个表格   2.延迟加载,只在需要时加载对象

一些建议将不胜感激

谢谢

2 个答案:

答案 0 :(得分:1)

您通过电子邮件ID查询不会花费太多时间。

  1. 客户表中的电子邮件列添加索引(请参阅此处以通过活动记录迁移添加索引 - {{3 }})

  2. 您的代码显示两次调用find_customer_id。这样做只有一次数据库查询被触发

  3. 您无需编写包装器方法 - Customer.find_by_email(customer_email)也可以使用

  4. 要进一步优化,您可以在一个循环中收集检查数据库中是否存在所需的所有客户ID,并触发单个数据库查询: Customer.where(email: [list of customer emails])

答案 1 :(得分:0)

主要问题是您错过了客户与调查之间的关联。您可以通过加入电子邮件来制作一个

class Survey < ActiveRecord::Base
  belongs_to :customer, primary_key: :email, foreign_key: :email
end

但这是一种略显粗略的方法。您的应用程序在填写调查时是否知道客户的ID?或者这些调查是否可由任何人填写,如果有人声称拥有与客户相同的电子邮件,您可以建立链接?

在任何情况下,您都需要将两个电子邮件列编入索引,如果您在两者之间建立关联,则可以在控制器代码中编写以下内容。

@store = Store.includes(surveys: :customer).find(params[store_id])

这将使数据库查询急切地加载您要显示的所有调查和客户,以便在循环内部您可以使用survey.customer而无需为每行调用新查询。