Elasticsearchでカタカナでソートする

前提条件

Elasticsearch + kuromoji
Ruby/Rails

前回の記事では、カタカナで検索するところまででした。

今回はカタカナで並び替え(ソート、sort)します。

前回の条件のまま、ソートの条件としてヨミガナ昇順、降順を指定したら、順番がめちゃくちゃになりました。おそらく文字コード順になってるのかなぁと推測しましたが、まぁわかりません。

追記: ここから
analyzerで分割した結果の中から採用されるそうです。詳しくはコメントをみてください。
追記: ここまで

そこで、なんかいい方法ないかなぁと調査していたら、本家のコードにありました。

elastic: String Sorting and Multifields

fieldsのrawに設定をすればよいようです。

"tweet": { 
    "type":     "string",
    "analyzer": "english",
    "fields": {
        "raw": { 
            "type":  "string",
            "index": "not_analyzed"
        }
    }
}

実験的に、これに合わせてfieldsを設定してみました。
省略されている箇所のコードを見たい人は前回の記事を見てください。

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
                  }
              }
    end
  end

end

その後、ソートしてみたところ、うまくいきました。

{ 
  query: {
    # その他の検索条件
  },
  sort: [{
    :'yomigana.raw' => :asc
  }]
}

やっと多少Elasticsearchの気持ちがわかってきたかな、というところです。
まだまだ分からないところだらけですが…。


カテゴリー Ruby, Ruby on Rails | タグ | パーマリンク

コメント・トラックバック一覧

  1. johtani says:

    前回の読みのフィールドでソートしたらおかしかったという話ですが、
    Elasticsearchは内部で、文字列をある特定の条件で単語に分割しています。
    分割する役割がanalyzerです。
    で、このanalyzerが分割した単語を内部で検索に利用しています。
    この分割された単語がソートにも利用されます。
    「ヒロシマ」は「ヒロ」「ヒロシ」「ロシ」「ロシマ」「シマ」という感じです。
    で、この分割された単語ですが、順序を保持しません。
    このデータを使って、ソートすると、これらの単語のうちソートに利用される値が「シマ」が採用されます。ソート対象のフィールドが複数のデータを持っている場合は(minがデフォルト)その中の一つが採用されます。なので、おかしくなるのかと。

    参照:https://www.elastic.co/guide/en/elasticsearch/guide/current/multi-fields.html#multi-fields

  2. 詳しい解説ありがとうございます!
    分割された単語が使われるんですね…。
    分割前のほうがいいということでしたら、analyzedを指定していましたが、not_analyzedを指定するのが正しそうですね。
    変更しておきました。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です