ElasticPress日本語設定2020年版
ElasticsearchをWordpressで利用するためのプラグインであるElasticPressのバージョンアップを行った際に、Elasticsearchのプラグインであるanalysis-sudachiが使用するsudachiの辞書を最新版に更新したところ、以前は得られていた検索結果が出なくなってしまったので、その対策をまとめてみました。
まずは問題となった辞書です。
「前回の記事」までは2019年3月8日版の「system_core.dic」を使用していました。これは「sudachi」がデフォルトで使用する辞書なので、特に設定等は行っておりませんでした。
新しい方が良いだろうという感覚で、単純に2020年7月22日版の「system_core.dic」に入れ替えたところ、期待した検索結果が出なくなってしまいました。
2019/03/08 -rw-r--r-- 1 501 212973212 8月 5 10:21 system_core.dic 2020/07/22 -rw-r--r-- 1 501 204650978 10月 26 21:30 system_core.dic
「sudachi」のシステム辞書は3種類あり、それぞれ「small」、「core」、「full」と呼ばれます。前述のとおり、辞書を指定しなければデフォルトでは「core」が使われます。辞書のバージョンが上がって検索結果が違ってくるのは想定外だったので、当初は違う原因を探っていましたが、最終的には辞書のバージョンであると判明しました。
まずは3種類ある辞書をそれぞれ使って検索結果を試すことにします。そのためには「sudachi」が使うシステム辞書の指定が必要ですが、なかなか情報がありません。試行錯誤の結果、以下の方法で指定することができることがわかりました。
まず、以下のような「sudachi」の設定ファイルを作成します。
デフォルトの「sudachi.json」に辞書指定を追加しただけです。
{ "systemDict" : "system_full.dic", "inputTextPlugin" : [ { "class" : "com.worksap.nlp.sudachi.DefaultInputTextPlugin" }, { "class" : "com.worksap.nlp.sudachi.ProlongedSoundMarkInputTextPlugin", "prolongedSoundMarks": ["ー", "-", "⁓", "〜", "〰"], "replacementSymbol": "ー"} ], "oovProviderPlugin" : [ { "class" : "com.worksap.nlp.sudachi.MeCabOovProviderPlugin" }, { "class" : "com.worksap.nlp.sudachi.SimpleOovProviderPlugin", "oovPOS" : [ "補助記号", "一般", "*", "*", "*", "*" ], "leftId" : 5968, "rightId" : 5968, "cost" : 3857 } ], "pathRewritePlugin" : [ { "class" : "com.worksap.nlp.sudachi.JoinNumericPlugin", "joinKanjiNumeric" : true }, { "class" : "com.worksap.nlp.sudachi.JoinKatakanaOovPlugin", "oovPOS" : [ "名詞", "普通名詞", "一般", "*", "*", "*" ], "minLength" : 3 } ] }
次に、「ElasticPress」のインデックス作成用のコードに「sudachi」設定ファイルを指定する行を追加します。同時に辞書のフォルダも指定しておきます。「settings_path」は設定ファイルそのものを指定し、「resources_path」はフォルダを指定します。辞書は設定ファイル内で指定するという複雑な関係を理解する必要がありました。
'analysis' => array( 'tokenizer' => array( 'sudachi_tokenizer' => array( 'type' => 'sudachi_tokenizer', 'split_mode' => 'C', 'settings_path' => '/etc/elasticsearch/sudachi/sudachi.json', 'resources_path' => '/etc/elasticsearch/sudachi_dict', ), ), 'analyzer' => array(
これで「ElasticPress」で「sudachi」の辞書を指定出来るようになったので「core」以外で試してみます。その結果、以前の期待値に一番近かったのは「small」を使用した時でした。結果オーライからすれば「small」使用でいいとは思いますが、せっかく辞書指定して「full」が使えるようになったのに「small」ではなんか納得行かないので、設定を変えてみます。
現在の「sudachi」バージョン(2.0.3)では、公式によれば以下のような分割モードがあるようです。
split_mode: Select splitting mode of Sudachi. (A, B, C) (string, default: C) C: Extracts named entities Ex) 選挙管理委員会 B: Into the middle units Ex) 選挙,管理,委員会 A: The shortest units equivalent to the UniDic short unit Ex) 選挙,管理,委員,会
前述のマッピングファイルの中で「split_mode」を「A」に変えてみます。
デフォルトの「C」では絞り込まれすぎていた検索結果が広がるようになりましたが、多少ノイズも含まれるようになりました。
'analysis' => array( 'tokenizer' => array( 'sudachi_tokenizer' => array( 'type' => 'sudachi_tokenizer', 'split_mode' => 'A', 'settings_path' => '/etc/elasticsearch/sudachi/sudachi.json', 'resources_path' => '/etc/elasticsearch/sudachi_dict', ), ), 'analyzer' => array(
マッピングはそのままにして、ここからは検索時の指定でチューニングすることにします。
'multi_match' => array( 'query' => $search_text, // 'type' => 'phrase', 'type' => 'best_fields', 'fields' => $search_fields, /** * Filter boost for post match phrase query * * @hook ep_match_phrase_boost * @param {int} $boost Phrase boost * @param {array} $prepared_search_fields Search fields * @param {array} $query_vars Query variables * @return {int} New phrase boost */ 'boost' => apply_filters( 'ep_match_phrase_boost', 3, $search_fields, $args ), // 'fuzziness' => apply_filters( 'ep_fuzziness_arg', 1, $search_fields, $args ), // 'operator' => 'and', ), ),
最後の2行がチューニングの結果採用した設定です。まず、「operator」で「and」指定したところ、また絞り込まれすぎたので、「fuzziness」を3段階のうちの中間設定にしてボカしてから絞り込むことで、以前の検索結果より、関連性が高いものが上位に来る、期待値としては良い結果が出るようになりました。最新の状態では、上記2行はコメント化しています。
タイトル画像:CopyRight: JASMINE