Elasticsearchでカタカナで検索する

現在、Elasticsearchと格闘中です。実験的に扱っているので、まだ本稼働に使ったりとかそういうことでもないのですが、とりあえずRailsで使う際に得られた知見をメモ的に書いておこうと思います。主に自分用です。体系的に書けそうになったらまた書きます。

今回は、カタカナでの検索のメモです。

ちなみに使っているプログラミング言語はRubyで、アプリケーションはRailsで作っていますので、それが前提です。

gemは、elasticsearch-railsとelasticsearch-modelを入れています。

Elasticsearch、日本語くらいでググるとkuromojiを使ったサンプルがよく出てきます。形態素解析でいろんなキーワードに分割されるので、検索の際の速度は上がるのですが、読み仮名(カタカナ)のような情報は区切りが判別しづらいので、tokenizerとしてkuromoji_tokenizerでは対応できません。例えば、「イオンモールオカヤマ」という文字列を解析させると、「イオン」「モールオカヤマ」の2つに分割されてしまい、「オカヤマ」で検索してもヒットしませんでした。

こういう場合は、nGramを使うのが定石のようです。nGramは、キーワードの文字列の長さをほぼ固定して分割していく方式で、色んなパターンにヒットするようになる代わりに、インデックス情報が膨らむようです。しかし、カタカナだけの場合など区切りがわかりにくい場合は、これが適しているとのことです。

では、elasticsearch-modelを使ったサンプルコードを載せてみます。

class Shop < ActiveRecord::Base
  include Elasticsearch::Model
  index_name [Rails.application.engine_name, Rails.env].join('_')
  settings index: {
               analysis: {
                   tokenizer: {
                       kuromoji_user_dict: {
                           type: :kuromoji_tokenizer
                       },
                       ngram_tokenizer: {
                           type: 'nGram',
                           min_gram: '2',
                           max_gram: '3',
                           token_chars: ['letter', 'digit']
                       }
                   },
                   filter: {
                       # 指定した品詞を除外する
                       pos_filter: {
                           type: :kuromoji_part_of_speech,
                           stoptags: ['助詞-格助詞-一般', '助詞-終助詞']
                       },
                       greek_lowercase_filter: {
                           type: :lowercase,
                           language: :greek,
                       },
                   },
                   analyzer: {
                       kuromoji_analyzer: {
                           type: :custom,
                           tokenizer: :kuromoji_user_dict,
                           filter: [:kuromoji_baseform, :pos_filter, :greek_lowercase_filter, :cjk_width]
                       },
                       ngram_analyzer: {
                           tokenizer: :ngram_tokenizer,
                           filter: [:cjk_width]
                       }
                   }
               }
           } do
    mapping do
      indexes :name,
              type: 'string',
              index: :analyzed,
              analyzer: :kuromoji_analyzer
      indexes :yomigana,
              type: 'string',
              index: :analyzed,
              analyzer: :ngram_analyzer
    end
  end
end

settingsのところで、tokenizerを2つ設定しています。そして、analyzerも2つ設定しています。
これらのanalyzerを、mappingのところでindexを作る際に利用しています。
kuromoji_analyzerは、普通の日本語の文字列に対して、
ngram_analyzerは、ヨミガナに対して使っています。

こうすることで、通常の日本語でも検索できるし、ヨミガナでも検索できるようになりました。


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

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

  1. Pingback: Elasticsearchでカタカナでソートする | 自転車で通勤しましょ♪ブログ

コメントを残す

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