私の環境
Mac OSX Yosemite
Ruby 2.2.2
Rails 4.2.1
まだElasticsearchと戦っています。
リレーション先とのデータ連携とかまではまだわかってないのですが、今のところはデータの取り込みの際にリレーション先を含める方法を取っています。そのリレーションのデータを包含するときにmappingする際のやり方がよくなかったようで、包含したデータを使ってソートすることができませんでしたが、解決したので書き方を載せておきます。
gem elasticsearch-modelを使っています。
変更前
ここでは、Shopモデルと、Companyモデルがあるという前提とします。
変更前は、mappingでindexを定義する際に、company.nameのように書いていました。
class Shop < Activerecord::Base
include Elasticsearch::Model
# index_nameは省略
settings index: {
# 省略
} do
mapping do
indexes :name,
type: 'string',
index: :analyzed,
analyzer: :kuromoji_analyzer
indexes :yomigana,
type: 'string',
index: :analyzed,
analyzer: :ngram_analyzer,
fields: {
raw: {
type: 'string',
index: :not_analyzed
}
}
indexes :'company.name', type: 'string', index: :analyzed, analyzer: :kuromoji_analyzer
indexes :'company.yomigana',
type: 'string',
index: :analyzed,
analyzer: :ngram_analyzer,
fields: {
raw: {
type: 'string',
index: :not_analyzed
}
}
end
end
def as_indexed_json
as_json(
include: {
company: { only: [:name, :yomigana] }
}
)
end
end
この状態で、ソートの条件としてcompany.yomigana.rawと指定しても、うまく機能しませんでした。
そこでelasticsearch-modelのソースコードを読んでみたところ、indexesメソッドにブロックが渡せることがわかったので、試してみることにしました。
変更後
indexesのネストで定義します。
ネストすると、companyをobjectとして定義するので、ソートの項目として使えるようになるようです(詳細なところはよくわかってません…)。
class Shop < Activerecord::Base
include Elasticsearch::Model
# index_nameは省略
settings index: {
# 省略
} do
mapping do
indexes :name,
type: 'string',
index: :analyzed,
analyzer: :kuromoji_analyzer
indexes :yomigana,
type: 'string',
index: :analyzed,
analyzer: :ngram_analyzer,
fields: {
raw: {
type: 'string',
index: :not_analyzed
}
}
indexes :company do
indexes :name, type: 'string', index: :analyzed, analyzer: :kuromoji_analyzer
indexes :yomigana,
type: 'string',
index: :analyzed,
analyzer: :ngram_analyzer,
fields: {
raw: {
type: 'string',
index: :not_analyzed
}
}
end
end
end
def as_indexed_json
as_json(
include: {
company: { only: [:name, :yomigana] }
}
)
end
end
その後、ソートしてみたところ、うまくいきました。
{
query: {
# その他の検索条件
},
sort: [{
:'company.yomigana.raw' => :asc
}]
}
やりたいことが大分できてきました。
