検索精度を高める
検索ネタを連発するのはElasticsearchやElasticPressがバージョンアップした時のお決まりですが、今回も検索ネタです。これまでは一つの検索手法で短い検索文字列と長い検索文字列の両方を対応しようとしていました。例えば「お弁当」と「日本人としては長い休み」などです。前者は検索したい文字列がほぼ確定していて、入力された検索文字列に対して完全一致に近い検査結果を表示して欲しいところです。一方、後者は比較的長い文字列を入力しているので、的確な分ち書きに基づいて分割されたインデックスを検索した結果を、ある程度絞り込んで表示されることが期待されています。具体的には「日本人」「長い」「休み」であいまい検索した上で、「and」条件で絞り込む、などです。
まずは、新たにElasticPress 3.5で導入された検索コードを見てみます。
if ( '3.5' === $search_algorithm_version ) { $query = array( 'bool' => array( 'should' => array( array( 'multi_match' => array( 'query' => $search_text, 'type' => 'phrase', '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 ), ), ),
「multi_match」の「type」に「phrase」を指定しているのが今回のバージョンアップのミソのようです。「前回」までの修正は、この部分を生かし切れていませんでしたので、これを生かした修正にしたいと思います。検索文字列の長さによって、実行される検索コードを分けるように変更します。どこからが長い検索文字列かってのは個人の主観もあるとは思いますが、ここでは「5文字」未満を短い文字列としました。
if ( '3.5' === $search_algorithm_version && mb_strlen( $search_text ) < 5 ) { $query = array( 'bool' => array( 'should' => array( array( 'multi_match' => array( 'query' => $search_text, 'type' => 'phrase', '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 ), ), ), --- 中略 --- } else { $query = array( 'bool' => array( 'should' => array( --- 中略 --- array( 'multi_match' => array( 'query' => $search_text, 'fields' => $search_fields, /** * Filter fuzziness for post query * * @hook ep_fuzziness_arg * @param {int} $fuzziness Fuzziness * @param {array} $prepared_search_fields Search fields * @param {array} $query_vars Query variables * @return {int} New fuzziness */ 'fuzziness' => apply_filters( 'ep_fuzziness_arg', 1, $search_fields, $args ), 'operator' => 'and', ), ),
検索文字列が「5文字」を超える場合には、「else」以下のコードが実行されます。あいまい検索で対象範囲を広げた上で、「and」で絞り込む手法を採用しました。この変更で、これまでより一層検索精度が高まったと思います。