LoginSignup
11
6

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-07-26

ゴール

本記事では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

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」を選択してください。
image.png
以下の画面に遷移するので一番左の「Sample eCommerce orders」の「Add data」を押下してください。
image.png
そうするとサンプルデータが用意されます。
Dev Toolsに移動して以下のクエリを投げてください。

GET kibana_sample_data_ecommerce/_search

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

クエリの紹介

基本的なクエリ

まずはElasticsearchの検索で良く使用されるmatch_phrasemulti_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"]
    }
  }
}


リクエスト
titlecontentに対して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"titleElastic 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 Stacktheをつけたとします。

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の解説を終わります。

おすすめ教材

11
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
6