Elasticsearchのハイライト機能を利用する際、ハイライトが破損した状態で返却してくることがあります。
一つの原因として考えられるのが、ハイライトのフラグメントを生成する際、サロゲートペアを1文字ではなく2文字としてカウントしてしまい、ハイライト生成の条件によってはサロゲートペアの文字コードの前半(上位サロゲート)のみを読み込んでしまうことです。
これは2019年にElasticsearchへ報告され、その後Luceneにtransferされましたが、いまだに修正されていません。
ただ、いくつか対策は存在するため、今回はそちらを紹介します。
number_of_fragmentsを0にする
ハイライトにはnumber_of_fragments
というオプションが存在し、返却するハイライトの数を指定することができます。
しかし、これを0にすることでハイライトを返す場合本文全てを返すようになります。フラグメントに切る処理をしないのでサロゲートペア問題が発生しないというわけですね。
本文の長さがある程度短い場合はこちらを検討するのも良いでしょう。
boundary_scannerをwordかsentenceにする
boundary_scannerというオプションはfragmentの切れ目を指定することが可能です。
chars
、word
、sentence
の3オプションが存在します。
chars
の場合はfragment_sizeに到達するとそこを切れ目にしますが、word
やsentence
にすることで切れ目を単語や文の終わりに調節することができます。
現在、chars
だと先述のバグが発生してしまうため、こだわりがなければword
やsentence
にすると良いでしょう。
boundary_scannerでchars
以外を設定する場合はboundary_scanner_localeを設定する
boundary_scanner
をword
やsentence
にすることで、fragmentを単語や文の終わりで切ってくれますが、言語によって切る基準は異なるので指定してあげる必要があります。
この場合、boundary_scanner_localeオプションを使います。
日本語の場合はja-JP
、英語の場合はen-US
を指定しましょう。
まとめ
ハイライトはオプションが多くハイライターによってデフォルト値が異なったりするため、どのオプションがどう効くのか整理して適用してあげることが大切です。
Elasticsearchの場合、公式ドキュメントが相当親切で、注釈などに引っかかりポイントや設計の考え方を書いてくれているため、そちらもしっかり目を通して先人の知恵を有効活用していきましょう
REF