Elasticsearch

Elasticsearch6系のauto_generate_phrase_query

本記事は「Elastic Stack」のアドベントカレンダー20日目の記事です。

概要

Elasticsearchでの日本語検索で、'東京都 東京タワー'のように、and検索でかつ'東京都'と'東京タワー'という2つの単語をフレーズとして検索したい。
「'東京'と'都'」とか「'東京'と'タワー'」とかではなく。

こういう場合、5系まではquery_stringでauto_generate_phrase_queryを使っていた。

5系までの場合

たとえば以下の3つドキュメントがあって、

東京タワーから見える東京都オフィス
日本の都、東京から見える東京タワー
東京都オフィスから見える東京タワー

analyzerは指定せずに

{"text": {"type": "text"}}

でindexすると、

以下のクエリで

{
    "profile": true,
    "query": {
        "query_string": {
            "query": "東京タワー 東京都",
            "auto_generate_phrase_queries": true,
            "default_operator": "and"
        }
    }
}

2つのドキュメントがヒットする

東京都オフィスから見える東京タワー
東京タワーから見える東京都オフィス

6系の場合

ただし、6系からauto_generate_phrase_queryが使えなくなった

version6.1.0で上と同じクエリを試すと全部のドキュメントがヒットする。

日本の都、東京から見える東京タワー 
東京都オフィスから見える東京タワー
東京タワーから見える東京都オフィス

profileでみるに+(text:\"東京 タワー\" text:東京タワー) +text:東京 +text:都となっていて、
東京都が、東京と都に分割されている。そしてand検索となるので都、東京がヒットしてしまう。

いや、東京都でヒットさせたい。

代替案

調べたところ2つほど近い結果を得られる方法があった。

1. quoteを使う

公式ドキュメントに書いてある通り、quoteを使ってみる。

{
    "profile": true,
    "query": {
        "query_string": {
            "query": "\"東京タワー\" \"東京都\"",
            "default_operator": "and"
        }
    }
}

同じように検索された!

東京タワーのら見える東京都オフィス
東京都オフィスから見える東京タワー

が、実際サービスで使うことを考えると単語ごとにクオートつけるのも微妙だし、ORとかに対応できない(対応するのは手間が多い)ので、クエリに手をいれるのは避けたい...

2. phrase検索

いくつか調べてみて、slopを多めにフレーズクエリを使えばいいのではと思ってやってみた。

{
    "profile": true,
    "query": {
        "multi_match": {
            "query": "東京都 東京タワー ",
            "fields": ["text"],
            "type": "phrase",
            "slop": 1000
        }
    }
}

いや、そうだよね。という結果。

東京都オフィスから見える東京タワー

間違ってはないんだけど、順番が考慮されるので微妙である。
あとは、slopの値とか適当にやってどうするんだとか

振り返って

本当はここでこういう代替案があります!(キリっ とかやりたかったけど、駄目だった。
もっといい方法はあるんだろうか...

サンタさん今年のプレゼントはいい感じの方法でお願いします。
そして、アドベントカレンダーでこういう投稿ですみませんm(__)m