Fessによるクローリングから検索までの仕組みの概要解説

全文検索エンジン搭載のオープンソースクローラーFessを利用していると、検索精度がやや悪いため、検索精度を改善したくなる事があるかと思います。

その際、内部構造を理解しているとどこのレイヤーをいじればいいか分かり易くなるので、以下の内容を理解しているとFessのハッキングに役立つかと思います。

FessとElasticsearchとLuceneの構造

Fess,Elasticsearch,Luceneのそれぞれの説明をしていきます。

クローリングと全文検索

Fessは全文検索クローラーです。検索エンジンElasticsearchをラッピングしているため、検索エンジン機能はElasticsearchが持っている機能で、クローリング部分の機能はFessが担っています。また、実はElasticsearch自体も全文検索エンジンLuceneをラッピングしています。Elasticsearchは、検索エンジンLuceneを非常に扱い易いAPIとしてラッピングしたものと言うことができます。Elasticsearchはその他にもKibanaなどのデータ可視化のツールなども導入できるようになっていたり、複数のサーバーにまたがってデータを保存する仕組みを提供していたりします。

構文解析と検索の仕組み

例えばドキュメント1に「明日は晴れ」という文章があったとします。「明日」というキーワードで検索できるようにするために、「明日 は 晴れ」という文章に解析されます。

次にドキュメント2には「明日は雨」という文章があったとします。「明日 は 雨」という文章に解析されます。

ドキュメント1,2は以下のようにインデクシングされます。

Index ドキュメント
明日 1,2
1,2
晴れ 1
2

このように、キーワード(term, もしくは token)に対してドキュメント番号が対応しているデータベースの仕組みを倒置インデックスと言います。

キーワードがインデックスに来ているため高速で検索ができるのです。

ドキュメントはこのように構文解析されるのですがこれだけではまだ検索ができません。

実はクエリー文字列も構文解析されなければいけません。

クエリー文字列の解析が無くとも、クエリー文字列が「明日」ならば問題なく検索できるのですが、クエリー文字列が「明日は雨」ならば、構文解析がなければどのindexともマッチしない事になります。

クエリー文字列も解析されて初めて「明日」「は」 雨」の3語全てにマッチするドキュメント2をヒットさせる事ができるようになります。

クローリング検索まで手順

クローリングして検索されるまでの仕組みを順を追って見て行きましょう。

1.インデックス(index)の定義

全文検索エンジンはLuceneの機能です。Luceneに保存するデータをIndexといいます。Lucene上でIndexを作成するにはJavaのコードやShellからの命令を発行する必要があるのですが、ElasticsearchはLuceneをラッピングし、HTTPのAPIからIndexを作成したり、Indexの定義ができるようにしています。Fessがインデックスの定義内容を決めていて、APIリクエストをElasticsearchに送り、ElasticsearchがLuceneへの処理に変換してIndexを作成しています。

2.クローリングからインデクシング(indexing)

ウェブサイトにhttpリクエストを送り、HTMLテキストを収集するのがクローリングです。Indexingはindexにデータを保存するプロセスの事です。Fessはクローリングしたデータを構文解析し、Elasticsearchが理解できるAPIに変換し、Web上のテキストをインデクシングしていきます。Indexingする際に、LuceneはAnalyzer(構文解析機)を使ってインデックスを作成していきます。構文解析機には日本語の解析機や英語の解析機など、様々な解析機があります。Luceneの解析機の設定をAPI経由で簡単に設定できるようにしているのがElasticsearchの役割で、Fessはクローリングしたテキストから適切な言語を判定し、適切な構文解析機を指定してElasticsearchにAPIを発行する役割を持っています。内部で実際に文章が構文解析されるのはLuceneのレイヤーです。

ここで注意するのは、HTMLの解析(パース)はFessが実行し、インデックスのための構文解析(tokenize)はLucene内部のAnalyzerが実行しているという点です。

3.クエリーの実行から検索結果の表示まで

Fessには検索窓があり、検索語句を受け取ります。Fessは検索語句を解析せず、そのままElasticsearchのAPIを経由して適切なAnalyzer指定などをしてクエリーリクエストを送ります。ElasticsearchはリクエストをLuceneへの処理へと変換します。LuceneはクエリーをAnalyzerを用いて構文解析(tokenize)し、toknizeされたクエリーとマッチするドキュメントをElasticsearchがAPI経由で返します。FessはElasticsearchから受け取ったデータをHTMLに埋め込んで検索結果一覧として表示します。