多くのサービスで使用されている全文検索エンジンのElasticsearch、以前自分も手を動かして触ってみましたが、今回は実際にどうやって検索をしているのか+αを調べたので、まとめてみることにしました。
ESの起源
Elastic社のCEOが、妻の料理レシピの情報を検索するためのアプリケーションとして開発されたそうで、ほっこりエピソードでした。
ESのクエリ
RDBのようにSQLでクエリを書くのではなく、jsonでクエリを作成し、検索を行う。
RDBとの語句の違い
ここを押さえとかないとドキュメントや記事を読んでも理解できない羽目に。
RDB | Elasticsearch |
---|---|
データベース | インデックス |
テーブル | マッピングタイプ |
カラム(列) | フィールド |
レコード(行) | ドキュメント |
検索について
まず、英語と日本語で、単語の区切りに違いがあります。
- 英語 : 空白
- 日本語 : 品詞の違い(分かりにくい)
検索の手法
そして、この単語を区切りにくい日本語に対応するために、2つの手法が存在します。
Ngram
-
N文字ずつ文章を釘って単語分解する方法
(例)N=2, 「東京都美術館」
⇨ 「東京」 「京都」 「都美」 「美術」 「術館」 -
検索を行う時には、件s買うクエリを単語分割し、ANDで結合する
「美術館」という検索クエリに対しては、「美術AND術館」
Ngramのメリット
- 部分一致検索できるため、検索の漏れがない
Ngramのデメリット
- 無意味な分割が多いため、インデックスが肥大化しやすい
「東京都美術館」の場合、「京都」という検索クエリに対してもヒットしてしまう。
↓
ユーザーが求めていない情報=検索ノイズ が多くなる。
形態素解析
- 事前に用意した辞書を用いて、意味のある単語で区切る
⇨ Ngramでの無意味な区切りがなくなる。
形態素解析の問題点
-
辞書の性能によっては謝った箇所で分解してしまう
(例)「外国人参政権」を、「外国」 「人参🥕」 「政権」 と分解してしまった場合、「参政権」 という検索クエリにヒットしない。 -
固有名詞を一単語とした場合
(例)「関西国際空港」 で一単語の場合、「国際空港」 「空港」 のような検索クエリでヒットしない
kuromoji
上記の問題を解決してくれるのが、日本語形態素解析エンジンの「kuromoji」
(例)「関西国際空港」 からプラスして、「関西」 「国際」 「空港」 の、辞書に基づいて分割した三単語、合計四単語でインデックスすることで、部分一致に対応。
(辞書、形態素解析の性能に依存するため、Ngramほどの部分一致には至らない)
形態素解析のメリット
- 検索ノイズが少ない
形態素解析のデメリット
- 辞書の性能によっては、検索漏れが発生
- 新しい単語(未知語・流行りの若者言葉)に弱い
Ngramと形態素解析の併用
検索ノイズ | 検索漏れ | |
---|---|---|
Ngram | 多い | 少ない |
形態素解析 | 少ない | 多い |
Ngramと形態素解析はトレードオフの関係性。
併用することで、精度を上げている。
インデックス生成
Ngramと形態素解析によるインデックスをそれぞれ生成 。
検索処理
二つのインデックスに対して同時に検索を行い、最終的に形態素解析による結果が先頭になりやすいよう重みをつけて検索結果をマージする。そうすることで、Ngramによる検索ノイズの結果を後ろに回し、ユーザーが理想とする表示結果を実現 。