【Elasticsearch入門】速習Elasticsearch Search query 基本クエリ(match, match_all)編

# ゴール
本記事ではElasticsearchの以下の基本操作の中のSearch queryの中の基本クエリ(match_all, match)を簡単に紹介します

- CRUD
- Search
    - query
        - 基本クエリ
            - match_all
            - match
            - match_phrase
            - multi_match
        - Termsクエリ
        - 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
```
レスポンスによりデータがあることが確認できると思います。
今回はこちらのデータを使用して説明を行っていきます。

# クエリの紹介
## 基本的なクエリ
まずはElasticsearchの検索で良く使用される`match_all`、`match`に関して説明していこうと思います。
これらのクエリには「対象のフィールドに対して全文検索を行う」と言った特徴があります。
つまり、基本的には単語分解して使用されるText型のフィールドに対して用いるものです。

それでは各クエリの説明に入っていきます。
### match_all
`match_all`は必ず全件を返すクエリです。
一般的にはドキュメントの確認に用いられるものです。

```
GET /{index}/_search 
{
  "query": {
    "match_all": {}
  }
}
```
**例**
リクエスト

```
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "match_all": {}
  }
}
```

レスポンス

```
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4675,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "kibana_sample_data_ecommerce",
        "_type" : "_doc",
        "_id" : "iZ4NgHMBFnhBnJdY3gCP",
...
```

レスポンスをみると`kibana_sample_data_ecommerce`のデータの全量が返ってくることがわかると思います。

### match
`match`は指定された語が含まれているかどうか、どれほどマッチしているかなどを判定して検索を行うクエリです。
ドキュメントの検索で最も使用されるクエリの一つです。
matchでは様々なオプションをつけることができるのでオプションも含めて説明していきます

#### 一般的な形

```
GET /{index}/_search 
{
  "query": {
    "match": {
      "{field}": "{value}"
    }
  }
}
```
**例**
リクエスト

```
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "match": {
      "products.product_name": "white"
    }
  }
}
```

レスポンス

```
...
  "hits" : [
      {
        "_index" : "kibana_sample_data_ecommerce",
        "_type" : "_doc",
        "_id" : "lp4OgHMBFnhBnJdYEQsr",
        "_score" : 2.7853389,
        "_source" : {
          "category" : [
            "Men's Clothing"
          ],
          "currency" : "EUR",
          "customer_first_name" : "Phil",
          "customer_full_name" : "Phil Allison",
          "customer_gender" : "MALE",
          "customer_id" : 50,
          "customer_last_name" : "Allison",
          "customer_phone" : "",
          "day_of_week" : "Friday",
          "day_of_week_i" : 4,
          "email" : "phil@allison-family.zzz",
          "manufacturer" : [
            "Elitelligence",
            "Low Tide Media"
          ],
          "order_date" : "2020-07-31T23:44:10+00:00",
          "order_id" : 581315,
          "products" : [
            {
              "base_price" : 24.99,
              "discount_percentage" : 0,
              "quantity" : 1,
              "manufacturer" : "Elitelligence",
              "tax_amount" : 0,
              "product_id" : 18944,
              "category" : "Men's Clothing",
              "sku" : "ZO0524305243",
              "taxless_price" : 24.99,
              "unit_discount_amount" : 0,
              "min_price" : 11.5,
              "_id" : "sold_product_581315_18944",
              "discount_amount" : 0,
              "created_on" : "2016-12-23T23:44:10+00:00",
              "product_name" : "Shirt - white",
...
```

上記はレスポンス内にある一部の結果を示しています。`products.product_name`をみてみると`white`が入っているドキュメントが返ってきているのがわかります。

#### OR検索
OR検索を行いたい場合、（つまり、複数語を指定してどれかが入っているという検索をしたい場合、）以下の通り、複数の検索ワードを指定することができます。

```
GET /{index}/_search 
{
  "query": {
    "match": {
      "{field}": "{value} {value2}"
    }
  }
}
```
検索ワードに`white black`の両方を指定した場合は以下のようになります。
**例**
リクエスト

```
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "match": {
      "products.product_name": "white black"
    }
  }
}
```

レスポンス

```
...
    "hits" : [
      {
        "_index" : "kibana_sample_data_ecommerce",
        "_type" : "_doc",
        "_id" : "k54OgHMBFnhBnJdYEQsr",
        "_score" : 3.1972795,
        "_source" : {
          "category" : [
            "Women's Clothing"
          ],
          "currency" : "EUR",
          "customer_first_name" : "Diane",
          "customer_full_name" : "Diane Reese",
          "customer_gender" : "FEMALE",
          "customer_id" : 22,
          "customer_last_name" : "Reese",
          "customer_phone" : "",
          "day_of_week" : "Wednesday",
          "day_of_week_i" : 2,
          "email" : "diane@reese-family.zzz",
          "manufacturer" : [
            "Pyramidustries"
          ],
          "order_date" : "2020-07-29T05:19:41+00:00",
          "order_id" : 577614,
          "products" : [
            {
              "base_price" : 20.99,
              "discount_percentage" : 0,
              "quantity" : 1,
              "manufacturer" : "Pyramidustries",
              "tax_amount" : 0,
              "product_id" : 14551,
              "category" : "Women's Clothing",
              "sku" : "ZO0170501705",
              "taxless_price" : 20.99,
              "unit_discount_amount" : 0,
              "min_price" : 10.08,
              "_id" : "sold_product_577614_14551",
              "discount_amount" : 0,
              "created_on" : "2016-12-21T05:19:41+00:00",
              "product_name" : "Blouse - black/white",
...
```

上記はレスポンス内にある一部の結果を示しています。`products.product_name`をみてみると`black/white`が入っているドキュメントが返ってきているのがわかります。
他の結果をみてみるとどちらかしか入っていないものもあるかと思います。
ただし、両方が含まれている場合、スコアが高くなるため、検索結果として上位に出てくるようになります。

#### AND検索


```
GET /{index}/_search 
{
  "query": {
    "match": {
      "{field}": {
         "query": "{value}",
         "operator": "and"
      }
    }
  }
}
```
検索ワードに`black shirt`の両方を指定した場合は以下のようになります。
**例**
リクエスト

```
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "match": {
      "products.product_name": {
        "query": "black shirt",
        "operator": "and"
      }
    }
  }
}
```

レスポンス

```
...
             {
              "base_price" : 29.99,
              "discount_percentage" : 0,
              "quantity" : 1,
              "manufacturer" : "Low Tide Media",
              "tax_amount" : 0,
              "product_id" : 11599,
              "category" : "Men's Clothing",
              "sku" : "ZO0417004170",
              "taxless_price" : 29.99,
              "unit_discount_amount" : 0,
              "min_price" : 14.99,
              "_id" : "sold_product_553396_11599",
              "discount_amount" : 0,
              "created_on" : "2016-12-03T05:48:29+00:00",
              "product_name" : "Shirt - black",
...
```

上記はレスポンス内にある一部の結果を示しています。`products.product_name`をみてみると`Shirt black`が入っているドキュメントが返ってきているのがわかります。
このようにOperatorで指定することでAND検索を行うことができます。


#### minimum_should_match
上記でOR検索とAND検索を行いました。
これら二つを行うことができるようになると今度はその間のような検索を行いたくなるかと思います。
具体的には、**３つの語のうち２つは一致してほしい**といった要件です。
そういったときに`minimum_should_match`を用います。

```
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "match": {
      "{field}": {
         "query": "{value1} {value2} {value3}",
        "minimum_should_match": N
      }
    }
  }
}
```
検索ワードに`black white shirt`の最低２つの文字を検索でひっかけたい時の例を示していきます。

**例**
リクエスト

```
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "match": {
      "products.product_name": {
        "query": "black white shirt",
        "minimum_should_match": 2
      }
    }
  }
}
```

レスポンス

```
...
         {
              "base_price" : 24.99,
              "discount_percentage" : 0,
              "quantity" : 1,
              "manufacturer" : "Elitelligence",
              "tax_amount" : 0,
              "product_id" : 18944,
              "category" : "Men's Clothing",
              "sku" : "ZO0524305243",
              "taxless_price" : 24.99,
              "unit_discount_amount" : 0,
              "min_price" : 11.5,
              "_id" : "sold_product_581315_18944",
              "discount_amount" : 0,
              "created_on" : "2016-12-23T23:44:10+00:00",
              "product_name" : "Shirt - white",
...
```

上記はレスポンス内にある一部の結果を示しています。`products.product_name`をみてみると`Shirt white`が入っているドキュメントが返ってきているのがわかります。
他の結果をみてみてもわかるとおり、最低２つの語が一致していることがわかります。

以上で`match`, `match_all`の解説を終わります。
次回は基本クエリの中の`match_phrase`, `multi_match`を解説していきます。


# おすすめ教材


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