LoginSignup
14
13

More than 3 years have passed since last update.

ElasticSearchの検索クエリに関して(基礎編)

Last updated at Posted at 2019-05-31

ElasticSearchの検索クエリに関して

目的

ElasticSearchの基本的な検索のやり方の説明と記述の仕方を説明する。

使用環境

  • Amazon Elasticsearch Service
    • Elasticsearch6.4
    • Kibana6.4

用語説明

Index

索引。
このindexに検索対称のドキュメントを格納。Indexは複数もつことが可能。
例:先頭にuser_price_index_がつくIndexが1日ごとに作られる

  • user_price_index_20190501
  • user_price_index_20190502
  • user_price_index_20190503
  • user_price_index_20190504

Type

リレーショナルデータベースでいえばテーブルに相当。
バージョン6以降は廃止される。

Document

格納されたドキュメント。
リレーショナルデータベースでいえば1レコードに相当。

サンプルログ

ユーザーがとあるお店で、商品を購入したと想定
東スーパー、西コンビニ、南商店、北デパートと4つのお店が存在し、以下の商品を購入

商品名 単価
キノコの山 120円
コアラのマーチ 92円
杉のこ村 111円
たけのこの里 140円
ハーゲンダッツ 1000円

ログはjson形式で登録されており以下のような構造になっている。

ユーザーがお店に行ったら作られるログ

{"user_id": 52, "kind_name": "アクセス", "place": "北デパート", "@timestamp": "2019-06-13T19:55:23+09:00:00"}

ユーザーが購入したら作られるログ

{"user_id": 43, "kind_name": "購入", "price": 140, "place": "南商店", "total_price": 280, "total_price_with_tax": 302.4, "product": "たけのこの里", "p_value": 2, "@timestamp": "2019-06-29T05:42:17+09:00:00"}

ログは1日ごとに作成されるuser_price_index_yyymmddという名前のIndexdocumentとして記録される。1

検索の基本

ElasticSeachは レコードの処理(検索、作成、更新、削除処理)が可能なREST APIが用意されているのでそれを利用する。

Kibana のDevToolを利用する場合は以下のように記述して、実行すれば検索可能。
検索パラメータははjson形式で記述する。

GET user_price_index_*/_search
{
  "size":3,
  "query": {
           ....
  }
}

sizeで取得件数を指定し、query内に検索条件を記述する

検索クエリ

自分がよく使う検索クエリとそのサンプルを紹介。

term

指定したフィールドを完全一致検索する。

term
"term":{
    "フィールド":検索値
}

文字列のフィールドを完全一致検索する場合はフィールド名に.keywordをつける。

term(テキスト検索の場合)
"term":{
    "フィールド.keyword":"検索値"
}

 
例:productが「杉のこ村」のdocumentを検索する場合の検索クエリ

リクエスト(productが「杉のこ村」の**document**を検索する場合の検索クエリ)
GET user_price_index_*/_search
{
  "size":3,
  "query": {
    "term":{
      "product.keyword":"杉のこ村"
    }
  }
}

検索結果
検索結果(productが「杉のこ村」の**document**を検索する場合の検索クエリ)
{
  "took": 60,
  "timed_out": false,
  "_shards": {
    "total": 145,
    "successful": 145,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 938,
    "max_score": 2.9618306,
    "hits": [
      {
        "_index": "user_price_index_20190608",
        "_type": "_doc",
        "_id": "BBmGxGoBzDMFYAVDLKj9",
        "_score": 2.9618306,
        "_source": {
          "user_id": 60,
          "kind_name": "購入",
          "price": 111,
          "place": "西コンビニ",
          "total_price": 444,
          "total_price_with_tax": 479.52,
          "product": "杉のこ村",
          "p_value": 4,
          "@timestamp": "2019-06-08T06:45:22+09:00:00"
        }
      },
      {
        "_index": "user_price_index_20190602",
        "_type": "_doc",
        "_id": "qxmIxGoBzDMFYAVDcLq0",
        "_score": 2.7725887,
        "_source": {
          "user_id": 1,
          "kind_name": "購入",
          "price": 111,
          "place": "西コンビニ",
          "total_price": 444,
          "total_price_with_tax": 479.52,
          "product": "杉のこ村",
          "p_value": 4,
          "@timestamp": "2019-06-02T07:30:48+09:00:00"
        }
      },
      {
        "_index": "user_price_index_20190604",
        "_type": "_doc",
        "_id": "ShmHxGoBzDMFYAVDqrUM",
        "_score": 2.7725887,
        "_source": {
          "user_id": 56,
          "kind_name": "購入",
          "price": 111,
          "place": "南商店",
          "total_price": 555,
          "total_price_with_tax": 599.4,
          "product": "杉のこ村",
          "p_value": 5,
          "@timestamp": "2019-06-04T20:21:35+09:00:00"
        }
      }
    ]
  }
}

terms

termの複数条件版。

terms
"terms":{
    "フィールド":[検索値1, 検索値2,...]
}

文字列のフィールドを完全一致検索する場合はフィールド名に.keywordをつける。

terms(テキスト検索の場合)
"terms":{
    "フィールド.keyword":["検索値1","検索値2",...]
}

例:productが「杉のこ村」と「きのこの山」のdocumentを検索する場合の検索クエリ

リクエスト(productが「杉のこ村」と「きのこの山」の**document**を検索する場合の検索クエリ)
GET user_price_index_*/_search
{
  "size":3,
  "query": {
    "terms":{
      "product.keyword":["杉のこ村","キノコの山"]
    }
  }
}

検索結果
検索結果(productが「杉のこ村」と「きのこの山」のdocumentを検索する場合の検索クエリ)
{
  "took": 18,
  "timed_out": false,
  "_shards": {
    "total": 145,
    "successful": 145,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1935,
    "max_score": 1,
    "hits": [
      {
        "_index": "user_price_index_20190601",
        "_type": "_doc",
        "_id": "0BmGxGoBzDMFYAVDLKX5",
        "_score": 1,
        "_source": {
          "user_id": 23,
          "kind_name": "購入",
          "price": 111,
          "place": "東スーパー",
          "total_price": 222,
          "total_price_with_tax": 239.76,
          "product": "杉のこ村",
          "p_value": 2,
          "@timestamp": "2019-06-01T19:19:35+09:00:00"
        }
      },
      {
        "_index": "user_price_index_20190601",
        "_type": "_doc",
        "_id": "_BmGxGoBzDMFYAVDLKj9",
        "_score": 1,
        "_source": {
          "user_id": 57,
          "kind_name": "購入",
          "price": 111,
          "place": "南商店",
          "total_price": 333,
          "total_price_with_tax": 359.64,
          "product": "杉のこ村",
          "p_value": 3,
          "@timestamp": "2019-06-01T14:38:21+09:00:00"
        }
      },
      {
        "_index": "user_price_index_20190601",
        "_type": "_doc",
        "_id": "KxmHxGoBzDMFYAVDqq0K",
        "_score": 1,
        "_source": {
          "user_id": 34,
          "kind_name": "購入",
          "price": 120,
          "place": "南商店",
          "total_price": 120,
          "total_price_with_tax": 129.6,
          "product": "キノコの山",
          "p_value": 1,
          "@timestamp": "2019-06-01T21:02:55+09:00:00"
        }
      }
    ]
  }
}

range

検索条件を範囲指定できるクエリ。

range
"range":{
  "フィールド名":{
    "gt": 範囲開始(境界含まない),
    "gte": 範囲開始(境界含む),
    "lt": 範囲終了(境界含まない),
    "lte": 範囲終了(境界含む),

}

検索条件が時間の場合

range(検索条件が時間の場合)
"range":{
  "フィールド名":{
    "time_zone": "タイムゾーン",
    "gt": 範囲開始(境界含まない),
    "gte": 範囲開始(境界含む),
    "lt": 範囲終了(境界含まない),
    "lte": 範囲終了(境界含む),
}

例:total_priceが500以上、1000未満のdocumentを検索する場合の検索クエリ

リクエスト(total_priceが500以上、1000未満の**document**を検索する場合の検索クエリ)

GET user_price_index_*/_search
{
  "size":3,
  "query": {
    "range":{
      "total_price":{
        "gte": 500,
        "lt": 1000
      }
    }
  }
}

検索結果
検索結果(total_priceが500以上、1000未満の**document**を検索する場合の検索クエリ)
{
  "took": 79,
  "timed_out": false,
  "_shards": {
    "total": 145,
    "successful": 145,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 817,
    "max_score": 1,
    "hits": [
      {
        "_index": "user_price_index_20190601",
        "_type": "_doc",
        "_id": "GRmHxGoBzDMFYAVDqrAL",
        "_score": 1,
        "_source": {
          "user_id": 81,
          "kind_name": "購入",
          "price": 140,
          "place": "南商店",
          "total_price": 700,
          "total_price_with_tax": 756,
          "product": "たけのこの里",
          "p_value": 5,
          "@timestamp": "2019-06-01T06:34:09+09:00:00"
        }
      },
      {
        "_index": "user_price_index_20190601",
        "_type": "_doc",
        "_id": "oRmHxGoBzDMFYAVDqrUM",
        "_score": 1,
        "_source": {
          "user_id": 59,
          "kind_name": "購入",
          "price": 140,
          "place": "東スーパー",
          "total_price": 700,
          "total_price_with_tax": 756,
          "product": "たけのこの里",
          "p_value": 5,
          "@timestamp": "2019-06-01T22:19:17+09:00:00"
        }
      },
      {
        "_index": "user_price_index_20190601",
        "_type": "_doc",
        "_id": "yBmIxGoBzDMFYAVDcLez",
        "_score": 1,
        "_source": {
          "user_id": 57,
          "kind_name": "購入",
          "price": 140,
          "place": "南商店",
          "total_price": 560,
          "total_price_with_tax": 604.8,
          "product": "たけのこの里",
          "p_value": 4,
          "@timestamp": "2019-06-01T23:42:33+09:00:00"
        }
      }
    ]
  }
}

例:2019-06-28に記録されたログを検索する場合のクエリ

リクエスト(2019-06-28に記録されたログを検索する場合のクエリ)

GET user_price_index_*/_search
{
  "size":3,
  "query": {
    "range":{
      "@timestamp":{
        "time_zone": "Asia/Tokyo",
        "gte": "2019-06-28T00:00:00",
        "lt": "2019-06-29T00:00:00"
      }
    }
  }
}

検索結果
検索結果(2019-06-28に記録されたログを検索する場合のクエリ)
{
  "took": 5,
  "timed_out": false,
  "_shards": {
    "total": 145,
    "successful": 145,
    "skipped": 140,
    "failed": 0
  },
  "hits": {
    "total": 217,
    "max_score": 1,
    "hits": [
      {
        "_index": "user_price_index_20190628",
        "_type": "_doc",
        "_id": "mhmGxGoBzDMFYAVDLKLc",
        "_score": 1,
        "_source": {
          "user_id": 83,
          "kind_name": "アクセス",
          "place": "北デパート",
          "@timestamp": "2019-06-28T06:41:56+09:00:00"
        }
      },
      {
        "_index": "user_price_index_20190628",
        "_type": "_doc",
        "_id": "JBmGxGoBzDMFYAVDLKPc",
        "_score": 1,
        "_source": {
          "user_id": 1,
          "kind_name": "アクセス",
          "place": "西コンビニ",
          "@timestamp": "2019-06-28T04:16:37+09:00:00"
        }
      },
      {
        "_index": "user_price_index_20190628",
        "_type": "_doc",
        "_id": "pBmGxGoBzDMFYAVDLKPc",
        "_score": 1,
        "_source": {
          "user_id": 57,
          "kind_name": "購入",
          "price": 120,
          "place": "西コンビニ",
          "total_price": 360,
          "total_price_with_tax": 388.8,
          "product": "キノコの山",
          "p_value": 3,
          "@timestamp": "2019-06-28T09:32:34+09:00:00"
        }
      }
    ]
  }
}

ElasticSearchシリーズ


  1. yyymmddには、ログを記録した日付が入る。例えば、2019-06-01に作成されたログなら20190601 

14
13
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
14
13