我已经编写了一些代码来搜索所有Recipe
条记录中的几个属性。代码有效,但我想要一些输入,如果它没问题,或者如何使它更好/更快。
我有一个包含name:string
和ingredients:[array of integers]
(postgres数据库)等各种属性的配方模型。成分是单独模型Ingredient
的ID。这是一次学习经历,我不想使用任何宝石。
我的表格 index.html.erb
<%= form_tag recipes_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= collection_select( :ingredients, :ingredient_ids, Ingredient.all, :id, :name, {:include_blank => false, include_hidden: false}, { :multiple => true } ) -%>
<%= submit_tag "Search" %>
</p>
<% end %>
recipes_controller.rb
def index
@recipes = Recipe.search(params[:search], params[:ingredients])
end
recipe.rb
def self.search(search, ids)
array = []
if search && !search.empty?
meals = where('name ILIKE ?', "%#{search}%")
meals.each do |meal|
array.push(meal)
end
if ids && !ids.empty?
ingredients(array, ids)
else
return array
end
elsif ids && !ids.empty?
ingredients(all, ids)
else
all
end
end
def self.ingredients(meals, ids)
newarray = []
if ids
meals.each do |me|
a = me.ingredients
b = ids[:ingredient_ids].map(&:to_i)
if (b - a).empty?
newarray.push(me)
end
end
return newarray
else
return meals
end
end
目前此工作正常,因为我没有很多记录,但我不相信如果我有数百或数千条记录,它会非常快。有关改善事物的建议吗?
答案 0 :(得分:0)
如果您知道要经常搜索一个或多个列,请尝试为这些列添加数据库级索引。没有索引,任何搜索都将是O(n)时间,其中n是记录数。但是,如果使用索引,则搜索将为O(log(n))时间,因为对于搜索列排序的数据,您可以通过它进行二进制搜索。
请查看http://weblog.rubyonrails.org/2011/12/6/what-s-new-in-edge-rails-explain/,了解有关如何检查查询效果是否可以改进的更多信息。
另外两个要考虑性能的事情:
1)对于你的所有情况,你可能会返回比你想要的更多的记录。你可能想考虑使用分页(我知道你没有提到其他宝石,但有一些great gems用于分页。)
2)如果您确实想要一次返回大量记录,请考虑使用ActiveRecord's batching(我通常使用#find_each)以确保您不会立即将所有内容加载到内存中并最终获得OOM- ING。