私の環境
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 }] }
やりたいことが大分できてきました。