Help us understand the problem. What is going on with this article?

Elasticsearchのbool queryを利用してAND OR NOTを書いてみる

More than 3 years have passed since last update.

初めてElasticsearchのクエリをビルドしたのでいろいろハマりました。SQLの世界観とちょっと違っていて、なれるまで時間がかかると思います。でも、なれたら複雑な検索条件をSQLより簡単に書けるかも知れません。

では、Elasticsearchの基礎クエリの一つ、Bool Queryを解説してみます。

Bool Queryについて

Elasticsearch 2.0からandクエリorクエリは全部非推奨になり、その代わりにboolクエリの方が推奨されます。Boolクエリは複数のクエリを組み合わせる(つまりAND、OR、NOTで結合)のに使います。

Boolクエリは4種類があります:must、 filter、 should、 must_notです。

クエリ 説明
must ANDとして使います。小クエリは総合スコアに影響を与えます
filter mustと同じくANDです。ただし、スコアは無視されます(総合スコアに影響を与えません)。
should ORとして使えます。 minimum_should_matchパラメータで最低マッチする条項の数が指定できます1
must_not NOTです。

使用例

AND条件

例えば、SQLはこういうSELECT文があります。

SELECT * FROM users WHERE age >= 25 AND salary >= 500000;

Elasticsearchのクエリに書き直すと、

{
  "query": {
    "bool" : {
      "must" : [
        { "range" : { "age" : { "gte": 25 } } },
        { "range" : { "salary" : { "gte": 500000  } } }
      ]
    }
  }
}

になります。今回はmustを使いますが、スコア無視したい場合はfilterを使えばいいのです。

OR条件

SELECT * FROM users WHERE age >= 25 OR salary >= 500000;

Elasticsearchのクエリに書き直すと、

{
  "query": {
    "bool" : {
      "should" : [
        { "range" : { "age" : { "gte": 25 } } },
        { "range" : { "salary" : { "gte": 500000  } } }
      ],
      "minimum_should_match" : 1
    }
  }
}

になります。

NOT条件

SELECT * FROM users WHERE user_id NOT BETWEEN 525 AND 600;

Elasticsearchのクエリに書き直すと、

{
  "query": {
    "bool" : {
      "must_not" : {
        "range" : { "user_id" : { "gte": 525, "lte": 600  } }
      }
    }
  }
}

になります。

AND、OR、NOTを組み合わせてみる

SELECT * FROM users WHERE (salary >= 500000 AND status = 'active')
                      OR (user_id NOT BETWEEN 525 AND 600);

Elasticsearchのクエリに書き直すと、

{
  "query": {
    "bool" : {
      "should" : [
         { 
           "bool" : {
             "must": [
               { "range": { "salary" : { "gte": 500000 } } },
               { "term": {"status": "active" } }
             ]
           } 
         },
         {
           "bool": {
             "must_not" : {
               "range" : { "user_id" : { "gte": 525, "lte": 600 } } 
             }
           }
         } 
       ]
    }
  }
}

になります。

注意したいのはboolクエリはネストができるため、いくら複雑な条件にしても表現できます。

まとめ

条件 SQL Elasticsearch
AND WHERE A AND B {"bool": {"must": [A,B]}
OR WHERE A OR B {"bool": {"should": [A,B]}
NOT WHERE NOT A {"bool": {"must_not": A}

おまけ

Elasticsearchクエリはポーランド記法と似ていますね。
例えば、3+4だったら+ 3 4になり、(1 + 5) * (2 + 3)だったら(* (+ 1 5) (+ 2 3))になりますね。なかなか面白いです!

では、よいサーチライフを!

参考文献


  1. 公式ドキュメントには書いてないがおそらくデフォルト値は1です。 

vanhuyz
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした