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

  • 66
    Like
  • 0
    Comment
More than 1 year has 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です。