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のデータを扱ううえで必要となるので、少しずつ慣れていきましょう(私自身も)!
ではでは👋