【Elastic】Search APIでデータを検索する

elasticseachはJSONベースの検索/分析エンジンで、データを蓄積するという点でDBのような特性も持ちます。

elasticsearchには豊富なAPIも用意されており、これらを介してデータのCRUD操作も可能です。

とりわけドキュメントの検索に用いるAPIはSearch APIと呼ばれ、よく利用されるAPIの1つだと思います。今回はそんなSearch APIの基本的な操作を、実際に試しながら紹介していきたいと思います。

実行環境

今回APIはKibanaの「開発ツール」から実行します。

検索対象のインデックス

サンプルデータとして提供されている「kibana_sample_data_ecommerce」のデータを検索してみます。データの中身は以下のようになっています(以下はサンプルのドキュメント1件分)。

検索

Search APIの基本

まずはSearch APIの基本構文です。

GET /<target>/_search

<target>には検索対象にしたいデータストリームやエイリアス、インデックス名を指定します。全てのデータを検索対象にしたい場合にはワイルドカード(*)または_allを指定します。

GET /kibana_sample_data_ecommerce/_search

以下、検索結果の例です。デフォルトでは10件分の結果が返されます。実際には4675件ヒットしていることがわかります(hits.value)。

{
  "took" : 4,
  "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" : "kUkLkXsBIQprJhqoPedv",
        "_score" : 1.0,
        "_source" : {
          "category" : [
            "Men's Clothing"
          ],
          "currency" : "EUR",
          "customer_first_name" : "Eddie",
          "customer_full_name" : "Eddie Underwood",
          "customer_gender" : "MALE",
          "customer_id" : 38,
          "customer_last_name" : "Underwood",
          "customer_phone" : "",
          "day_of_week" : "Monday",
          "day_of_week_i" : 0,
          "email" : "eddie@underwood-family.zzz",
          "manufacturer" : [
            "Elitelligence",
            "Oceanavigations"
          ],
          "order_date" : "2021-09-13T09:28:48+00:00",
          "order_id" : 584677,
          "products" : [
            {
              "base_price" : 11.99,
              "discount_percentage" : 0,
              "quantity" : 1,
              "manufacturer" : "Elitelligence",
              "tax_amount" : 0,
              "product_id" : 6283,
              "category" : "Men's Clothing",
              "sku" : "ZO0549605496",
              "taxless_price" : 11.99,
              "unit_discount_amount" : 0,
              "min_price" : 6.35,
              "_id" : "sold_product_584677_6283",
              "discount_amount" : 0,
              "created_on" : "2016-12-26T09:28:48+00:00",
              "product_name" : "Basic T-shirt - dark blue/white",
              "price" : 11.99,
              "taxful_price" : 11.99,
              "base_unit_price" : 11.99
            },
            {
              "base_price" : 24.99,
              "discount_percentage" : 0,
              "quantity" : 1,
              "manufacturer" : "Oceanavigations",
              "tax_amount" : 0,
              "product_id" : 19400,
              "category" : "Men's Clothing",
              "sku" : "ZO0299602996",
              "taxless_price" : 24.99,
              "unit_discount_amount" : 0,
              "min_price" : 11.75,
              "_id" : "sold_product_584677_19400",
              "discount_amount" : 0,
              "created_on" : "2016-12-26T09:28:48+00:00",
              "product_name" : "Sweatshirt - grey multicolor",
              "price" : 24.99,
              "taxful_price" : 24.99,
              "base_unit_price" : 24.99
            }
          ],
          "sku" : [
            "ZO0549605496",
            "ZO0299602996"
          ],
          "taxful_total_price" : 36.98,
          "taxless_total_price" : 36.98,
          "total_quantity" : 2,
          "total_unique_products" : 2,
          "type" : "order",
          "user" : "eddie",
          "geoip" : {
            "country_iso_code" : "EG",
            "location" : {
              "lon" : 31.3,
              "lat" : 30.1
            },
            "region_name" : "Cairo Governorate",
            "continent_name" : "Africa",
            "city_name" : "Cairo"
          },
          "event" : {
            "dataset" : "sample_ecommerce"
          },
        --------------略----------------------------------------
        }
      }
  ]
  }
}

クエリパラメータ

ここでは、検索時の条件(どのフィールドを取得するか、何件取得するかなど)を指定します。検索結果に対するクエリ(フィルタリング)はこのパラメータの中の”query”内で記述します(後述)。

取得フィールドの指定

全てのフィールドを取得する必要がない場合(特定のフィールドのみ取得したい場合)は”_source”を指定します。

フィールドは配列で指定しますが、キーを”includes”とした場合は指定したフィールドのみが、”excludes”とした場合は指定したフィールド以外が取得できます。

#指定したフィールドのみ取得
GET /kibana_sample_data_ecommerce/_search
{
  "_source": {
        "includes": ["user", "type"]
    }
}

#指定したフィールド以外を取得
GET /kibana_sample_data_ecommerce/_search
{
  "_source": {
        
        "excludes": ["user", "type"]
    }
}

取得件数の指定

デフォルトでは10件しか取得できませんが、”size”を指定することで、任意の件数を取得することもできます。

指定の位置からドキュメントを取得したい場合は、”from”を指定します。”from”はスキップするドキュメントの数を指定し、デフォルトは0です。例えば10に指定した場合、ヒットしたドキュメントの10番目以降が検索対象になります。

パフォーマンスの観点から一度に取得できる最大ドキュメント数は10000件に制限されている点注意してください。

#2番め以降200件を取得
GET /kibana_sample_data_ecommerce/_search
{
    "size": 200,
    "from": 2
}

ソート

検索結果をソートして取得したい場合は”sort”を指定します。キーをフィールド名、値に降順or昇順を指定します。もちろん複数フィールドを指定することも可能です。

#userフィールドの降順
GET /kibana_sample_data_ecommerce/_search
{
    "sort": [
      {
        "user": {
          "order": "desc"
        }
      }
    ]
}


#複数フィールドで指定する場合
GET /kibana_sample_data_ecommerce/_search
{
    "sort": [
      {
        "user": {
          "order": "desc"
        },
        "currency": {
          "order": "asc"
        }
      }
    ]
}

検索結果のフィルタリング

全件検索

どのような条件で検索するかについては”query”で指定します。全件検索する場合は条件を”match_all”とします。

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

条件指定

テキストで検索する場合は”match”を用います。以下ではcurrencyフィールドがEURのドキュメントだけを取得します。全文検索となるので、「EU」や「UR」で検索するとヒットしません。

GET /kibana_sample_data_ecommerce/_search
{
    "query": {
      "match": {
        "currency": "EUR"
      }
    }
}

数値のフィールドでは範囲指定も可能です。以下の例はtaxless_total_priceが10以上20以下のドキュメントを検索しています。

※matchで特定の数値だけ検索も可能です。

GET /kibana_sample_data_ecommerce/_search
{
    "query": {
      "range": {
        "taxless_total_price": {
          "gte": 10,
          "lte": 20
        }
      }
    }
}

複数条件の指定

複数条件を指定して検索することもできます。この場合は”query”の”bool”を用います。

AND条件の場合は”must”を、OR条件の場合は”should”を指定します。

#AND条件の場合
GET /kibana_sample_data_ecommerce/_search
{
    "query": {
    
      "bool": {
        "must": [
          {"match": {
            "currency": "EUR"
            }
          },
          {
            "match": {
              "day_of_week_i": 2
            }
          }
        ]
      }
    }
}


#OR条件の場合
GET /kibana_sample_data_ecommerce/_search
{
    "query": {
    
      "bool": {
        "should": [
          {"match": {
            "currency": "EUR"
            }
          },
          {
            "match": {
              "day_of_week_i": 2
            }
          }
        ]
      }
    }
}

まとめ

elasticsearchのSearch APIを用いてデータを検索する基本的な操作を紹介しました。今回の内容の他にも、カスタマイズをした検索が可能です。

SQLと書き方が異なるので慣れるまで大変かもしれないですが、elasticsearchのデータを扱ううえで必要となるので、少しずつ慣れていきましょう(私自身も)!

ではでは👋