11

Tire と ActiveRecord を使用して、elasticsearch のデータ セットのインデックスを作成しています。has_many :images の Artist モデルがあります。特定の画像を返す Artist モデルのメソッドにインデックスを付けるにはどうすればよいですか? または、関連付けられたモデルのメソッドを参照しますか? 希望するアーティストの結果には、アーティストに関連付けられたプライマリ イメージ (オリジナルとサムネイルの両方) のパスが含まれます。

私はこのマッピングを試しました:

mapping do
  indexes :id,                  :index    => :not_analyzed
  indexes :name                     
  indexes :url
  indexes :primary_image_original       
  indexes :primary_image_thumbnail
end

これらの Artist メソッドを参照するには:

    def primary_image_original  
        return images.where(:priority => 'primary').first.original
    end

    def primary_image_thumbnail
        return images.where(:priority => 'primary').first.thumbnail_150
    end

これは、インデックス付きのメソッドを無視するだけです。Elasticsearch、Tire、ネストされたクエリ/ ActiveRecord との関連付けなどの他の回答に基づいて、これを試しました:

mapping do
  indexes :id,                  :index    => :not_analyzed
  indexes :name 
  indexes :url
  indexes :images do
    indexes :original
    indexes :thumbnail_150
    indexes :priority
  end
end

def to_indexed_json
    to_json(include: { images: { only: [:original, :thumbnail_150, :priority] } } )
end

しかし、これも私が求めているものを返しません。私は数時間をグーグルで検索し、elasticsearch と Tire のドキュメントを読んでいますが、従うべきこのパターンの実例は見つかりませんでした。アイデアをありがとう!

4

1 に答える 1

6

したがって、インデックス作成の問題に対するソリューションをここに含めます。

関連付けの索引付け

メソッドにインデックスを付ける 1 つの方法は、to_json呼び出しに含めることです。

def to_indexed_json
  to_json( 
    :only   => [ :id, :name, :normalized_name, :url ],
    :methods   => [ :primary_image_original, :primary_image_thumbnail, :account_balance ]
  )
end

もう 1 つは:as、マッピング ブロックでオプションを使用することです。

mapping do
  indexes :id, :index    => :not_analyzed
  indexes :name             
  # ...

  # Relationships
  indexes :primary_image_original, :as => 'primary_image_original'
  indexes :account_balance,        :as => 'account_balance'
end

インポート時のn+1クエリとの戦い

インデックス作成が遅い問題は、おそらくデータベース内のn+1クエリによるものです。インデックスを作成するアーティストごとに、画像 (オリジナルとサムネイル) のクエリを発行します。関連するレコードを 1 つのクエリで結合すると、はるかにパフォーマンスが向上します。Rails ガイドのEager Loading Associationsを参照してください。

TireIndex#importメソッドと import Rake タスクを使用すると、パラメーターを渡すことができます。パラメーターは、ネットワーク経由で paginate メソッドに送信されます。

それでは、単純なアプローチを比較してみましょう。

bundle exec rake environment tire:import CLASS=Article FORCE=true
Article Load (7.6ms)  SELECT "articles".* FROM "articles" LIMIT 1000 OFFSET 0
Comment Load (0.2ms)  SELECT "comments".* FROM "comments" WHERE ("comments".article_id = 1)
Comment Load (0.1ms)  SELECT "comments".* FROM "comments" WHERE ("comments".article_id = 2)
...
Comment Load (0.3ms)  SELECT "comments".* FROM "comments" WHERE ("comments".article_id = 100)

そして、includeフラグメントを渡すと:

bundle exec rake environment tire:import PARAMS='{:include => ["comments"]}'  CLASS=Article FORCE=true 
Article Load (8.7ms)  SELECT "articles".* FROM "articles" LIMIT 1000 OFFSET 0
Comment Load (31.5ms) SELECT "comments".* FROM "comments" WHERE ("comments".article_id IN (1,2, ... ,100))

はるかに良い :) 試してみて、問題が解決するかどうかお知らせください。


Article.importRailsコンソールで試すこともできますArticle.import(include: ['comments'])補足として、この正確な問題が、 Tireparamsのインポート ツールチェーン全体でハッシュをサポートする理由でした。

于 2012-12-12T20:20:15.403 に答える