【Elasticsearch入門】速習Elasticsearch Search query Termベースクエリ編

# ゴール
本記事ではElasticsearchの以下の基本操作の中のSearch queryの中の基本クエリ(match_phrase, multi_match)を簡単に紹介します
※最初の方のパートはElasticsearchの説明やデータの準備パートとなっているため [【Elasticsearch入門】速習Elasticsearch Search query 基本クエリ(match, match_all)編](https://qiita.com/doiken_/items/062d5391146b5b0b6618)と内容が被っているので読み飛ばしても構いません。

- CRUD
- Search
    - query
        - 基本クエリ
        - Termクエリ
            - term
            - terms
            - range
        - Boolクエリ
    - aggregation

# Elasticsearch
Elasticsearch は オープンソースの全文検索エンジンです。
Apache LuceneをベースとしたJavaで書かれたソフトウェアでElastic社により開発が進められています。
登録したドキュメントから目的の単語を含むドキュメントを高速に検索することができます。
基本的にElasticsearchではRestful APIを使って操作します。

# バージョン等
Elasticsearch: 7.6.2
kibana: 7.6.2
※ 簡単にSearch queryの操作を行うためにKibanaのDevToolsを使用します。

# 環境準備
環境に関しては以下の投稿に記載の通りで用意しています。
[【Elasticsearch入門】環境構築](https://qiita.com/doiken_/items/fbbaf835710a1827e2f1)
[【Elasticsearch入門】環境構築 Windows編](https://qiita.com/doiken_/items/7847f8fd2bd65ceeaf18)

# 準備
サンプルデータの用意をしていきます。
Kibanaの初期画面で「Add sample data」を選択してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/617075df-05da-01c6-d516-188077c76912.png)
以下の画面に遷移するので一番左の「Sample eCommerce orders」の「Add data」を押下してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/187c0277-111a-9fd2-97be-0fc48246da4f.png)
そうするとサンプルデータが用意されます。
Dev Toolsに移動して以下のクエリを投げてください。

```
GET kibana_sample_data_ecommerce/_search
```
レスポンスによりデータがあることが確認できると思います。
今回はこちらのデータを使用して説明を行っていきます。

# クエリの紹介
## Termベースクエリ
今回はTermベースクエリを紹介していこうと思います。Termベースクエリには主に３つのクエリ`term`, `terms`, `range`といったクエリがあります。

「対象のフィールドに対して完全一致検索を行う＆範囲検索を行う」といった特徴があります。
つまり、文字型に関してはKeyword型のフィールドに対して用いるものです。

それでは各クエリの説明に入っていきます。
### termクエリ
`term`はTermベースクエリの基本となるクエリです。
term句の中にフィールド名と検索キーワードを指定して完全一致検索を行います。
完全一致検索なので大文字小文字も区別されます。

#### 基本構文
```
GET /{index}/_search 
{
  "query" : {
    "term" : {
      "{field}" : "{value}"
    }
  }
}
```
**例**
リクエスト

```
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "term": {
      "customer_gender": "MALE"
    }
  }
}
```

レスポンス

```
...
"hits" : [
      {
        "_index" : "kibana_sample_data_ecommerce",
        "_type" : "_doc",
        "_id" : "iZ4NgHMBFnhBnJdY3gCP",
        "_score" : 0.7348517,
        "_source" : {
          "category" : [
            "Men's Clothing"
          ],
          "currency" : "EUR",
          "customer_first_name" : "Ahmed Al",
          "customer_full_name" : "Ahmed Al Morris",
          "customer_gender" : "MALE",
...
```

レスポンスをみると`customer_gender`に対する`value`の値が`MALE`で完全一致しているものしか含まれていないのがわかるかと思います。

Keyword型かどうかの確認を行いたい場合、以下のクエリを投げると確認を行うことができます。

```
GET kibana_sample_data_ecommerce/_mapping
```

一部の結果を以下に表示します。

```
...
       "customer_first_name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "customer_full_name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
...
```
この結果からわかる通り、いくつかのフィールドでは複数の型を持つことができます。
こういった時、keyword型を指定した検索を行うこともできます。

**例**
リクエスト

```
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "term": {
      "customer_first_name.keyword": "Ahmed Al"
    }
  }
}
```
レスポンス

```
...
          "currency" : "EUR",
          "customer_first_name" : "Ahmed Al",
          "customer_full_name" : "Ahmed Al Morris",
          "customer_gender" : "MALE",
          "customer_id" : 4,
          "customer_last_name" : "Morris",
          "customer_phone" : "",
          "day_of_week" : "Tuesday",
          "day_of_week_i" : 1,
          "email" : "ahmed al@morris-family.zzz",
          "manufacturer" : [
            "Low Tide Media",
            "Microlutions"
          ],
...
```

また、termクエリでKeyword型以外の検索はできません（厳密には検索はできるが想定の結果が返ってこない）が、matchクエリでKeyword型の検索を行うことはできます。
以下のクエリは上記と同じ結果を返します。

```
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "match": {
      "customer_first_name.keyword": "Ahmed Al"
    }
  }
}
```


### Termsクエリ
TermsクエリはTermクエリと同じように完全一致検索を行うクエリです。
検索キーワードを複数指定することができる点が異なります。
どれか一つでもヒットすれば結果を返します

#### 基本構文
```
GET /{index}/_search 
{
  "query" : {
    "terms" : {
      "{field}" : ["{value1}", "{value2}", "{value3}"
    }
  }
}
```
**例**
リクエスト

```
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "terms": {
      "customer_first_name.keyword": ["Ahmed Al", "Muniz", "Elyssa"]
    }
  }
}
```

レスポンスは省略します。


### rangeクエリ
rangeクエリ数値型や日付型を対象として値の範囲検索を行います。

#### 基本構文
```
GET /{index}/_search 
{
  "query" : {
    "range" : {
      "{greater_operator}" : "{value1}",
      "{lower_operator}" : "{value2}"
    }
  }
}
```
`greater_operator`は以下の二つのいずれかのオペレータが入ります。

- `gte`: 〜以上
- `gt`: より大きい

`lower_operator`は以下の二つのいずれかのオペレータが入ります。

- `lte`: 〜以下
- `lt`: より小さい


**例**
リクエスト

```
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "range": {
      "taxful_total_price": {
        "gte": 10,
        "lte": 20
      }
    }
  }
}
```

レスポンス

```
          "taxful_total_price" : 19.98,
          "taxless_total_price" : 19.98,
          "total_quantity" : 2,
          "total_unique_products" : 2,
          "type" : "order",
          "user" : "robbie",
...
```

レスポンスをみると`taxful_total_price`の値が10〜20のものが返却されていることがわかると思います。

また、日付型のフィールドを対象とした検索も行うことができます。
以下が例となります。

```
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "range": {
      "order_date": {
        "gte": "2020-08-01",
        "lte": "2020-08-02"
      }
    }
  }
}
```

また、日付型のフィールでの範囲検索では日付計算式を使用することができます。
以下の例では
「`今の時間から1日前`〜`2020-08-02`」の間での検索を行う。
といったものになります。

```
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "range": {
      "order_date": {
        "gte": "now-1d",
        "lte": "2020-08-02"
      }
    }
  }
}
```
これ以外にも日付計算式では以下の表現が使用可能です。

- `y` : `年`
- `M` : `月`
- `w` : `週`
- `d` : `日`
- `h` : `時間`
- `m` : `分`
- `s` : `秒`

是非これらの表現を使いこなして柔軟な検索を行ってください。

以上でTermベースクエリの解説を終わります。


# おすすめ教材


- [はじめてのElasticsearch](https://www.udemy.com/course/elasticsearch/?couponCode=3BE4592DF570D6DA69CF)
- [はじめてのKibana](https://www.udemy.com/course/kibana-jap/?couponCode=E59890B71A886D5A1CED)