私はElasticSearchをタイヤジェムと一緒に使用して、サイトの検索機能を強化しています。必要な結果を得るためにデータをマッピングおよびクエリする方法を理解するのに問題があります。
関連するコードは以下のとおりです。その下にも、望ましいアウトバットについて説明します。
# models/product.rb
class Product < ActiveRecord::Base
include Tire::Model::Search
include Tire::Model::Callbacks
has_many :categorizations
has_many :categories, :through => :categorizations
has_many :product_traits
has_many :traits, :through => :product_traits
mapping do
indexes :id, type: 'integer'
indexes :name, boost: 10
indexes :description, analyzer: 'snowball'
indexes :categories do
indexes :id, type: 'integer'
indexes :name, type: 'string', index: 'not_analyzed'
end
indexes :product_traits, type: 'string', index: 'not_analyzed'
end
def self.search(params={})
out = tire.search(page: params[:page], per_page: 12, load: true) do
query do
boolean do
must { string params[:query], default_operator: "OR" } if params[:query].present?
must { term 'categories.id', params[:category_id] } if params[:category_id].present?
# if we aren't browsing a category, search results are "drill-down"
unless params[:category_id].present?
must { term 'categories.name', params[:categories] } if params[:categories].present?
end
params.select { |p| p[0,2] == 't_' }.each do |name,value|
must { term :product_traits, "#{name[2..-1]}##{value}" }
end
end
end
# don't show the category facets if we are browsing a category
facet("categories") { terms 'categories.name', size: 20 } unless params[:category_id].present?
facet("traits") {
terms :product_traits, size: 1000 #, all_terms: true
}
# raise to_curl
end
# process the trait facet results into a hash of arrays
if out.facets['traits']
facets = {}
out.facets['traits']['terms'].each do |f|
split = f['term'].partition('#')
facets[split[0]] ||= []
facets[split[0]] << { 'term' => split[2], 'count' => f['count'] }
end
out.facets['traits']['terms'] = facets
end
out
end
def to_indexed_json
{
id: id,
name: name,
description: description,
categories: categories.all(:select => 'categories.id, categories.name, categories.keywords'),
product_traits: product_traits.includes(:trait).collect { |t| "#{t.trait.name}##{t.value}" }
}.to_json
end
end
上記のように、「product_traits」フィールドから必要なものを取得するために、elasticsearchとの間でデータの前処理/後処理を行っています。これは正しくないと感じていることであり、私の質問の出所です。
私は製品の大規模なカタログを持っており、それぞれに色、素材、ブランドなどのいくつかの「特徴」があります。これらの特性は非常に多様であるため、特定の製品の特性の値を保持するProductTraitモデルを介して製品モデルに関連する特性モデルを含むようにデータをモデル化しました。
最初の質問は次のとおりです。これらの特性に適切にインデックスを付けるためにelasticsearchマッピングを作成するにはどうすればよいですか?これにはネストされたタイプが含まれていると思いますが、ドキュメントを理解するのに十分な意味がありません。
2番目の質問:ファセットをグループに戻したい(上記の方法の最後で処理している方法で)が、各特性に対して現在選択されている値を考慮せずに、search
一致する数を反映するカウントを使用する。例:ユーザーが「Glitter」を検索してから「BlueColor」ファセットに対応するリンクをクリックした場合、すべての「Color」ファセットを表示したままにし
、「BlueColor」フィルターなしでクエリ結果に対応するカウントを表示します。 。それが良い説明であることを願っています。さらに明確にする必要がある場合は申し訳ありません。