布団の中にいたい

Elasticsearchいじったり、Androidアプリ書いたり。最近は数学の勉強が楽しくなってきました。

query stringが自由すぎてびっくりした話

Elasticsearchを使って実際に検索するときに便利なクエリがQueryStringQuerySimpleQueryStringQueryです。これらはqueryでfieldを指定したりAND・OR・NOTを指定できたりするのでかなり自由度が高いクエリです。

この2つのクエリ、使う分にはかなり便利なのですが、分かってないで使うと非常に危なさそうだったので、備忘録代わりに書きます。

SimpleQueryStringQueryとQueryStringQueryはquery_stringのパラメータとして、fieldsを指定することで、そのfieldsの中から検索をすることができるのですが、QueryStringの場合、queryに直接fieldと値を指定されてしまうと、その条件で検索をかけてしまいます。

以下のmappingでindexを作成したとします。 sampleというtypeでidとuser_idというpropertyを定義しています。propertyはともにkeywordです。

{
    "mappings": {
        "sample": {
            "properties": {
                "id": {
                    "type": "keyword"
                },
                "user_id": {
                    "type": "keyword"
                }
            }
        }
    }
}

上記のmappingのindexに以下のデータを入れているとします。

{ "id": "test1", "user_id": "user_id1"}
{ "id": "test2", "user_id": "user_id2"}
{ "id": "test3", "user_id": "user_id3"}

そして以下のクエリを投げると、まさかidがtest2のdocumentが引っこ抜けてしまいます。

GET sample/sample/_search
{
    "query": {
        "query_string": {
            "query": "id:test2",
            "fields": ["user_id"]
        }
    }
}

ちなみにSimpleQueryStringQueryの場合だと指定したfieldsから検索されるので検索結果は空で返ってきます。

まとめ

QueryStringQueryとSimpleQueryStringQueryはとても便利なのですが、私みたいによく分かっていない状態で使うと色々危ないので、無難に検索するのであれば、MultiMatchQueryを使うのが無難かもしれないです。もっと細かい検索(AND・OR・NOTなど)を使いたいのであれば、自前でquery builderを書いたほうがいいんですかね。