初めに
Sudachi Elasticsearchプラグインが新しくリリースされました。以前のバージョンで課題となっていた重複解析問題が解決され、解析が場合によって数倍速くなりました。
重複解析解析問題
同じテキストを複数のAnalyzerに掛けるともっと検索の精度を上げることができます(A単位とC単位で解析した結果をそれぞれフィールドに入れるなど)。なので文章を解析するときに複数のAnalysis Chainを設定することがあります。例えば、次の設定例(フルバージョン)では4つのフィールドが設定されています。単語の見出しだけではなく、読み、読みのローマ字、辞書形がインデックスに入っています。
{
"mappings": {
    "properties": {
      "text": {
        "type": "text",
        "analyzer": "sudachi_a_analyzer", // # 1
        "fields": {
          "reading_romaji": {
            "type": "text",
            "analyzer": "sudachi_romaji_analyzer" // # 2
          },
          "reading_katakana": {
            "type": "text",
            "analyzer": "sudachi_readingform_analyzer" // # 3
          },
          "baseform": {
            "type": "text",
            "analyzer": "sudachi_baseform_analyzer" // # 4
          }
        }
      }
    }
  }
}
プラグインの3.0.0以前のバージョンはAnalysis Chainの数だけ解析を行っていましたが、3.0.0以上では解析結果がキャッシュされるため重複していたAnalysis Chain3つ分速くなります。
制限と正しい使い方
この改善は解析のキャッシングによって行っているものですので、メモリーが無制限に使われることを防ぐため入力が長い時はキャッシングが使われません。具体的な制限はUTF-16のコードユニット(例えばJavaでのString.length()が返す値)32k分です。
幸いにこの制限を回避するための措置があります。Elasticsearchにテキストを32kユニット以内に分割してArrayとして渡すと、Arrayの中身が連結されているかのように解析が行われます。
curl -X PUT "localhost:9200/sudachi_test/_doc/test-doc" \
 -H 'Content-Type: application/json' \
 -d @- <<EOF
{"text":"このドキュメントが非常に長ければ文章が複数回解析されます"}
EOF
解析する文章を段落単位に分けて、Arrayとしてドキュメントに入れないと長いドキュメントでは最適化が無効になる可能性があります。
curl -X PUT "localhost:9200/sudachi_test/_doc/test-doc" \
 -H 'Content-Type: application/json' \
 -d @- <<EOF
{"text":["Arrayとして渡せば", "長い文章を分割することができます"]}
EOF
bashの<<EOFの記法は https://qiita.com/take4s5i/items/e207cee4fb04385a9952 で解説されています。
実験
実験としてWikipediaのダンプをElasticsearchに入れました。コードは https://github.com/eiennohito/wikipedia-benchmark です。
実験は2つのパソコンで行っていて、1つ目のPCはベンチマークのコードを実行し、ネットワークを通じてドキュメントをElasticsearchに追加します。2つ目のPCはElasticsearchのサーバーとして動きます。実験では1万記事をインポートしています。記事は段落ごとに分けてArrayとして渡しています。
比較結果は次のテーブルにまとめています。1万記事のインポートが3.3倍速くなりました。
| コミット | インポート時間、秒 | 比較係数 | 
|---|---|---|
| 2ed32e8 (改善前) | 558.7 | 3.3 | 
| 838f680 (改善後) | 167.4 | 1.0 | 
おわりに
Elasticsearch-sudachi v3.0.0では同じフィールドを違う設定で解析するようなケースで高速に解析されるようになりました。ただし、長い文書では段落などでArrayに分ける必要があります。
これまでの Java のコードをKotlinで再実装しています。不具合などありましたら、issueをお願いいたします。
ではよい Sudachi life を。
