首先,我还是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.延迟加载,只在需要时加载对象
一些建议将不胜感激
谢谢
答案 0 :(得分:1)
您通过电子邮件ID查询不会花费太多时间。
为客户表中的电子邮件列添加索引(请参阅此处以通过活动记录迁移添加索引 - {{3 }})
您的代码显示两次调用find_customer_id
。这样做只有一次数据库查询被触发
您无需编写包装器方法 - Customer.find_by_email(customer_email)
也可以使用
要进一步优化,您可以在一个循环中收集检查数据库中是否存在所需的所有客户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
而无需为每行调用新查询。