ゴール
本記事ではElasticsearchの以下の基本操作の中のSearch queryの中の基本クエリ(match_phrase, multi_match)を簡単に紹介します
※最初の方のパートはElasticsearchの説明やデータの準備パートとなっているため 【Elasticsearch入門】速習Elasticsearch Search query 基本クエリ(match, match_all)編と内容が被っているので読み飛ばしても構いません。
- CRUD
- Search
- query
- 基本クエリ
- match_all
- match
- match_phrase
- multi_match
- Termsクエリ
- Boolクエリ
- 基本クエリ
- aggregation
- query
Elasticsearch
Elasticsearch は オープンソースの全文検索エンジンです。
Apache LuceneをベースとしたJavaで書かれたソフトウェアでElastic社により開発が進められています。
登録したドキュメントから目的の単語を含むドキュメントを高速に検索することができます。
基本的にElasticsearchではRestful APIを使って操作します。
バージョン等
Elasticsearch: 7.6.2
kibana: 7.6.2
※ 簡単にSearch queryの操作を行うためにKibanaのDevToolsを使用します。
環境準備
環境に関しては以下の投稿に記載の通りで用意しています。
【Elasticsearch入門】環境構築
【Elasticsearch入門】環境構築 Windows編
準備
サンプルデータの用意をしていきます。
Kibanaの初期画面で「Add sample data」を選択してください。
以下の画面に遷移するので一番左の「Sample eCommerce orders」の「Add data」を押下してください。
そうするとサンプルデータが用意されます。
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
の例を示すにあたって今のサンプルデータでは多少わかりにくいので新たなインデックスを作成してそれを使用しようと思います。
以下のクエリを実行して5つのドキュメントがあるインデックスを作成してください。
(ちなみにこれらのcontent
の内容はElasticsearchの公式ドキュメントに記載されているものです。時間があれば読んでみてください。勉強になります。)
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."
}
}
]
}
レスポンスをみると、3つのドキュメントが返されていることがわかります。
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
の検索でのスコアリングをより柔軟に行ってくれるためのオプションとなっています。
他にも様々な設定ができるようになっているのでぜひ公式ドキュメントを参考にいろいろ試してみてください。
以上でmatch
, match_all
の解説を終わります。