前回のエントリで、弊社サービス Re:lation が Elasticsearch をどういう感じで使っているのかを、主にインフラにまつわる部分を中心に書きました。
今回は実装に関わる部分を書いてみたいと思います。
前回の記事も含めて今回の記事につきましても、誤っている箇所がありましたら是非ご指摘ください。
形態素解析かN-gramか?
リリース当初は、日本語検索なんだから、 kuromoji
っしょ、と思い、 kuromoji
を使うことにしました。
kuromoji
は形態素解析器です。ドキュメントの本文も、検索キーワードも形態素にわけて検索します(厳密に言えば analyzer
の設定次第なんでしょうが)。
しかし問題がおこりました。
「大阪大学」というキーワードで検索すると、「大阪」で検索した結果や「大学」で検索した結果も含まれてしまうのです。メールボックスを検索する上であまりうれしくはありません。当然スコアが高い順に表示したら「大阪大学」で検索したものが上にくると思いますが、感覚的にもご理解いただけると思いますが、メールの検索ではスコア順ではなく最近のメールから表示してほしいです。また、自分のメールボックスを検索する場合は完全一致がうれしいだろうと思います。RDBMSで言うところの LIKE 検索がしたいのです。
そこで N-gram です。N-gram そのものの説明は割愛します。
最低2文字以上で検索するのであれば bi-gram (2-gram)
でもいいのですが、1文字で検索したいことはあります。「橘さん」からのメールはとりあえず「橘」で検索したくなるでしょう。Tokenizer は以下のように設定しています。
tokenizer: { message_ngram_tokenizer: { type: "ngram", min_gram: 1, max_gram: 2, token_chars: [ "letter", "digit", "punctuation", "symbol" ] } }
N-gram を使うメリットとしては、
- LIKE 検索が実現できる
- 未知語については考えなくていい
kuromoji
と違って elasticsearch に内包されている
があり、
デメリットとしては、
- インデックスサイズが大きくなる
- 類義語検索やあいまい検索ができない
があげられると思います。
実は kuromoji
を使った場合も EXTENDED
という、未知語は uni-gram (1-gram) に分割するという形態素解析とN-gramのハイブリッドのようなモードがあります。
これは当時試してはみましたが、詳しくは忘れましたが思うように検索できないことがあり断念しました。おそらく上述の「大阪大学」のような未知語ではないワードが分割され検索されてしまったのだと思います。
今回のエントリはここまで。