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

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

- 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_phrase`、`multi_match`に関して説明していこうと思います。
これらのクエリには「対象のフィールドに対して全文検索を行う」といった特徴があります。
つまり、基本的には単語分解して使用されるText型のフィールドに対して用いるものです。

それでは各クエリの説明に入っていきます。
### match_phrase
`match_phrase`では、複数のキーワードを指定した際に、指定された語順のドキュメントのみを検索することができます。
matchクエリでは語順がバラバラでも検索にヒットしますが、`match_phrase`では語順もチェックされます。

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

```
GET kibana_sample_data_ecommerce/_search
{
  "query" : {
    "match_phrase" : {
      "products.product_name": "Polo shirt"
    }
  }
}
```

レスポンス

```
...
           "products" : [
            {
              "base_price" : 11.99,
              "discount_percentage" : 0,
              "quantity" : 1,
              "manufacturer" : "Elitelligence",
              "tax_amount" : 0,
              "product_id" : 14615,
              "category" : "Men's Clothing",
              "sku" : "ZO0569605696",
              "taxless_price" : 11.99,
              "unit_discount_amount" : 0,
              "min_price" : 6,
              "_id" : "sold_product_574744_14615",
              "discount_amount" : 0,
              "created_on" : "2016-12-19T00:46:05+00:00",
              "product_name" : "Polo shirt - white",
...
```

レスポンスをみると`product_name`に対する`value`の値に`Polo shirt`が含まれるものが返されていることがわかると思います。

`match_phrase`には少し便利な機能があり、「間にN個の文字が含まれることを認める」といったクエリの渡し方ができます。
`slop`というものを使います。
以下が構文となります。

#### `slop`を使った構文
```
GET /{index}/_search 
{
  "query" : {
    "match_phrase" : {
      "{field}" : {
         "query": "{value}",
         "slop": "{N}"
      }
    }
  }
}
```
**例**
リクエスト

```
GET kibana_sample_data_ecommerce/_search
{
  "query" : {
    "match_phrase" : {
      "products.product_name": 
      {
        "query": "Polo white",
        "slop": 1
      }
    }
  }
}
```

レスポンス

```
...
           "products" : [
            {
              "base_price" : 11.99,
              "discount_percentage" : 0,
              "quantity" : 1,
              "manufacturer" : "Elitelligence",
              "tax_amount" : 0,
              "product_id" : 14615,
              "category" : "Men's Clothing",
              "sku" : "ZO0569605696",
              "taxless_price" : 11.99,
              "unit_discount_amount" : 0,
              "min_price" : 6,
              "_id" : "sold_product_574744_14615",
              "discount_amount" : 0,
              "created_on" : "2016-12-19T00:46:05+00:00",
              "product_name" : "Polo shirt - white",
...
```

レスポンスをみると`product_name`に対する`value`の値に`Polo white`が含まれており、その間の`shirt`という一文字分の猶予があることがわかります。
このように`slop`を使うことで柔軟性を持って`match_phrase`を使用することができます
※ `-`もありますが、これは形態素解析で除外されるので含まれません。

### multi_match
複数のフィールドをまたいで検索を行いたい時があると思います。
例えば、ブログのタイトルと本文を検索したい場合などです。
そういった際に良く使われるのが`multi_match`となります。
#### 準備
`multi_match`の例を示すにあたって今のサンプルデータでは多少わかりにくいので新たなインデックスを作成してそれを使用しようと思います。
以下のクエリを実行して５つのドキュメントがあるインデックスを作成してください。
（ちなみにこれらの`content`の内容はElasticsearchの[公式ドキュメント](https://www.elastic.co/guide/en/elasticsearch/reference/current/elasticsearch-intro.html)に記載されているものです。時間があれば読んでみてください。勉強になります。）

```
PUT my_index/_doc/1
{
  "title": "Elasticsearch",
  "content": "Elasticsearch is the distributed search and analytics engine at the heart of the Elastic Stack. Logstash and Beats facilitate collecting, aggregating, and enriching your data and storing it in Elasticsearch. Kibana enables you to interactively explore, visualize, and share insights into your data and manage and monitor the stack. Elasticsearch is where the indexing, search, and analysis magic happens."
}

PUT my_index/_doc/2
{
  "title": "Kibana",
  "content": "Elasticsearch is the distributed search and analytics engine at the heart of the Elastic Stack. Logstash and Beats facilitate collecting, aggregating, and enriching your data and storing it in Elasticsearch. Kibana enables you to interactively explore, visualize, and share insights into your data and manage and monitor the stack. Elasticsearch is where the indexing, search, and analysis magic happens."
}

PUT my_index/_doc/3
{
  "title": "Elasticsearch",
  "content": "While not every problem is a search problem, Elasticsearch offers speed and flexibility to handle data in a wide variety of use cases:"
}

PUT my_index/_doc/4
{
  "title": "Kibana",
  "content": "While not every problem is a search problem, Elasticsearch offers speed and flexibility to handle data in a wide variety of use cases:"
}

PUT my_index/_doc/5
{
  "title": "Elastic Stack",
  "content": "While not every problem is a search problem, Elasticsearch offers speed and flexibility to handle data in a wide variety of use cases:"
}

```

以下のクエリでインデックスが作成できたことを確認してください。

```
GET my_index/_search
```
確認ができたら`multi_match`を使ってみましょう。

#### 基本構文
```
GET /{index}/_search 
{
  "query" : {
    "match_phrase" : {
      "query" : "{value}",
      "fields": ["title", "content"]
    }
  }
}
```
**例**
リクエスト
`title`と`content`に対して`Elastic`, `Stack`というワードのOR検索をかけたいと思います。
それぞれのフィールドに対する検索の仕方はmatchクエリと同様、デフォルトでOR検索となります。

```
GET my_index/_search
{
  "query" : {
    "multi_match": {
      "query": "Elastic Stack",
      "fields": ["title", "content"]
    }
  }
}
```

レスポンス

```
 "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 2.1784627,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 2.1784627,
        "_source" : {
          "title" : "Elastic Stack",
          "content" : "While not every problem is a search problem, Elasticsearch offers speed and flexibility to handle data in a wide variety of use cases:"
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.7835206,
        "_source" : {
          "title" : "Elasticsearch",
          "content" : "Elasticsearch is the distributed search and analytics engine at the heart of the Elastic Stack. Logstash and Beats facilitate collecting, aggregating, and enriching your data and storing it in Elasticsearch. Kibana enables you to interactively explore, visualize, and share insights into your data and manage and monitor the stack. Elasticsearch is where the indexing, search, and analysis magic happens."
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.7835206,
        "_source" : {
          "title" : "Kibana",
          "content" : "Elasticsearch is the distributed search and analytics engine at the heart of the Elastic Stack. Logstash and Beats facilitate collecting, aggregating, and enriching your data and storing it in Elasticsearch. Kibana enables you to interactively explore, visualize, and share insights into your data and manage and monitor the stack. Elasticsearch is where the indexing, search, and analysis magic happens."
        }
      }
    ]
  }
```

レスポンスをみると、３つのドキュメントが返されていることがわかります。
`title`に一致している`"_id" : "5"`のものと`content`に一致している`"_id" : "1"`、`"_id" : "2"`とのものがあります。
そして、`"_id" : "5"`のスコアの方が他の二つより高いこともわかるかと思います。
これはスコアリングの仕方にもよりますが、`"_id" : "5"`の`title`に`Elastic Stack`という語が占める割合が大きいため、より高いスコアになっていることはなんとなく想像がつくかと思います。
例えば、どうしても`content`での一致度を優先させたいといった場合、

```
"content" → "content^2"
```
といった書き方に変更することで`content`での検索の一致度を優先してくれます。
では、やってみましょう。

リクエスト

```
GET my_index/_search
{
  "query" : {
    "multi_match": {
      "query": "Elastic Stack",
      "fields": ["title", "content^2"]
    }
  }
}
```
レスポンス

```
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 3.5670412,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 3.5670412,
        "_source" : {
          "title" : "Elasticsearch",
          "content" : "Elasticsearch is the distributed search and analytics engine at the heart of the Elastic Stack. Logstash and Beats facilitate collecting, aggregating, and enriching your data and storing it in Elasticsearch. Kibana enables you to interactively explore, visualize, and share insights into your data and manage and monitor the stack. Elasticsearch is where the indexing, search, and analysis magic happens."
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 3.5670412,
        "_source" : {
          "title" : "Kibana",
          "content" : "Elasticsearch is the distributed search and analytics engine at the heart of the Elastic Stack. Logstash and Beats facilitate collecting, aggregating, and enriching your data and storing it in Elasticsearch. Kibana enables you to interactively explore, visualize, and share insights into your data and manage and monitor the stack. Elasticsearch is where the indexing, search, and analysis magic happens."
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 2.1784627,
        "_source" : {
          "title" : "Elastic Stack",
          "content" : "While not every problem is a search problem, Elasticsearch offers speed and flexibility to handle data in a wide variety of use cases:"
        }
      }
    ]
  }
```

`"_id" : "1"`、`"_id" : "2"`のスコアが`"_id" : "5"`を上回ったことがわかります。
このようにどこかのフィールドだけ強調したい場合は, `^N`というものを使うと良いです。

また、**検索をmatch_phraseのようにしたい場合、どうしたら良いか？**といった疑問もあるかと思います。
例えば、以下のようにそういった需要があるかは置いておいて`Elastic Stack`に`the`をつけたとします。

```
GET my_index/_search
{
  "query" : {
    "multi_match": {
      "query": "the Elastic Stack",
      "fields": ["title", "content"]
    }
  }
}
```
レスポンス

```
 "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 3.2321887,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 3.2321887,
        "_source" : {
          "title" : "Elasticsearch",
          "content" : "Elasticsearch is the distributed search and analytics engine at the heart of the Elastic Stack. Logstash and Beats facilitate collecting, aggregating, and enriching your data and storing it in Elasticsearch. Kibana enables you to interactively explore, visualize, and share insights into your data and manage and monitor the stack. Elasticsearch is where the indexing, search, and analysis magic happens."
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 3.2321887,
        "_source" : {
          "title" : "Kibana",
          "content" : "Elasticsearch is the distributed search and analytics engine at the heart of the Elastic Stack. Logstash and Beats facilitate collecting, aggregating, and enriching your data and storing it in Elasticsearch. Kibana enables you to interactively explore, visualize, and share insights into your data and manage and monitor the stack. Elasticsearch is where the indexing, search, and analysis magic happens."
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 2.1784627,
        "_source" : {
          "title" : "Elastic Stack",
          "content" : "While not every problem is a search problem, Elasticsearch offers speed and flexibility to handle data in a wide variety of use cases:"
        }
      }
    ]
  }
```
この時確かに`"_id": "5"`は`Elastic Stack`という語を`title`にもちますが、望んだ結果ではありません。
※そのような需要はないかもしれないですが、今回は `the Elastic Stack`を検索したいという意図です。

この時、`"type": "phrase"`というフィールドをつけることでそれぞれのフィールドに対してmatch_phraseのような検索を行うことができます。

```
GET my_index/_search
{
  "query" : {
    "multi_match": {
      "query": "the Elastic Stack",
      "fields": ["title", "content"],
      "type": "phrase"
    
    }
  }
}
```
レスポンス

```
 "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 2.1823945,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 2.1823945,
        "_source" : {
          "title" : "Elasticsearch",
          "content" : "Elasticsearch is the distributed search and analytics engine at the heart of the Elastic Stack. Logstash and Beats facilitate collecting, aggregating, and enriching your data and storing it in Elasticsearch. Kibana enables you to interactively explore, visualize, and share insights into your data and manage and monitor the stack. Elasticsearch is where the indexing, search, and analysis magic happens."
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 2.1823945,
        "_source" : {
          "title" : "Kibana",
          "content" : "Elasticsearch is the distributed search and analytics engine at the heart of the Elastic Stack. Logstash and Beats facilitate collecting, aggregating, and enriching your data and storing it in Elasticsearch. Kibana enables you to interactively explore, visualize, and share insights into your data and manage and monitor the stack. Elasticsearch is where the indexing, search, and analysis magic happens."
        }
      }
    ]
  }
```

`"_id": "5"`はなくなったかと思います。
このように`"type"`フィールドは`multi_match`の検索でのスコアリングをより柔軟に行ってくれるためのオプションとなっています。
他にも様々な設定ができるようになっているのでぜひ[公式ドキュメント](https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-multi-match-query.html)を参考にいろいろ試してみてください。

以上で`match`, `match_all`の解説を終わります。


# おすすめ教材



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