2017-11-19 7 views
0

すべての私のRecipeレコードのいくつかの属性を使って検索するコードを書いています。コードはうまくいきますが、大丈夫かどうか、またはそれをより良く/より速くする方法については、いくつかの情報を入力したいと思います。Ruby on Rails - 複数の属性を持つレコードを検索する

私はname:stringingredients:[array of integers](postgresデータベース)を含むさまざまな属性を持つレシピモデルを持っています。成分は別のモデルのIDですIngredient。これは学習経験であり、私は宝石を使いたくない。

マイフォーム 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

頻繁に1つ以上の列を検索することがわかっている場合は、それらの列のデータベースレベルのインデックスを追加してみてください。索引がない場合、検索は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を終了させないようにしてください。

関連する問題