Elastic Certified Engineer Exam対策 – Search Data 1 <検索・集計・分析>

Banner for Elastic Certified Engineer Exam prep, with a trainer icon and Japanese subtitle, and a vertical 'TRAINING' label on the right. トレーニング

このブログの目的

本ブログシリーズの目的は、Elastic Certified Engineer Examの合格に必要な知識と実装スキルを体系的に習得することです。

Elastic Certified Engineer Examでは、Elasticsearchに対して適切な検索クエリを作成し、必要なデータを取得・分析できる能力が求められます。単純なキーワード検索だけでなく、Bool Queryによる条件検索、Aggregationによる集計・分析、検索結果の並び替えやページングなど、実務で利用される機能について理解しておく必要があります。

本記事では、Elastic Certified Engineer Examでよく利用されるQuery DSLを中心に解説します。Query DSLの基本構造からBool Query、Aggregation、Scoreの考え方までを段階的に学習し、試験問題だけでなく実務でも活用できる検索スキルの習得を目指します。また、本記事は、Elastic社が公開している試験ガイドの以下の試験範囲に関連する内容を扱います。

Searching Data – Write and execute a search query for terms and/or phrases in one or more fields of an index

Searching Data – Write and execute a search query that is a Boolean combination of multiple queries and filters

Searching Data – Write and execute metric and bucket aggregations

Searching Data – Write and execute aggregations that contain sub-aggregations

特にAggregationは試験でも重要な出題範囲であり、Bucket Aggregation・Metric Aggregation・Pipeline Aggregationの違いと使い分けを理解しておくことが重要です。本記事を通じて、Elasticsearchにおける検索と集計の基本を体系的に整理していきましょう。

Query概要

Elasticsearchでは、検索・集計・分析を行うために複数のクエリ言語が提供されています。最も基本となるのはJSON形式で記述するQuery DSL(Domain Specific Language)であり、Elastic Certified Engineer Examでも重要な試験範囲の一つです。

本記事では、試験で利用されるQuery DSLを中心に解説していきますが、まずはElasticsearchで利用できる代表的なクエリ言語を確認しておきましょう。

Query内容
Query DSLElasticsearchの標準的な検索・集計用クエリ
(Elastic Certified Engineer Exam での重点項目)
Elastic SQLSQLライクな構文で検索・集計を実行
KQLKibana上でデータを絞り込むためのクエリ言語
EQLSecurity分野で利用されるイベント相関分析向けクエリ言語
ES|QL検索・変換・集計を統合したパイプライン型クエリ言語

2026年6月時点で、Elastic Certified Engineer Examで使用される検索クエリは主にQuery DSLです。そのため、試験対策としてはまずQuery DSLの理解と実装に重点を置くことが重要です。

一方で、近年はES|QLの機能拡張が継続的に行われており、Elastic Stackにおける活用範囲も拡大しています。現時点では試験範囲の中心ではありませんが、今後の動向については把握しておくとよいでしょう。

クエリDSLの基本構造

Elasticsearchでは、_search APIに対して検索条件をJSON形式で渡すことでデータを検索します。

検索リクエストは、大きく以下の2つで構成されています。

  • リクエスト行(HTTPメソッド + APIエンドポイント)
  • 検索条件を記述するJSONボディ

検索条件を記述するJSONボディには、検索・集計・並び替え・ページングなどを制御するためのトップレベルフィールドが存在します。

本章では、Query DSLを構成する主要なトップレベルフィールドについて確認していきます。

リクエスト行(HTTPメソッド + エンドポイント)

リクエスト行は、HTTPメソッドとAPIエンドポイントで構成されます。ElasticsearchはREST APIを採用しているため、まずどのAPIをどのIndexに対して実行するのかを指定する必要があります。

検索を行う場合は、通常 _search APIを利用します。

参考クエリ

GET kibana_sample_data_flights/_search
  • GET:HTTPメソッド
  • kibana_sample_data_flights:検索対象Index
  • _search:検索API

query

query はQuery DSLの中心となるトップレベルフィールドです。どのDocumentを検索結果として取得するかを定義します。

利用頻度の高いクエリとして、matchtermrangebool などがあります。Elastic Certified Engineer Examでは、これらのクエリを組み合わせて条件を作成する問題が出題されます。

特に bool クエリは複数条件を組み合わせる際の基本となるため、理解しておくことが重要です。

参考クエリ

GET kibana_sample_data_flights/_search
{
  "query": {
    "range": {
      "FlightDelayMin": {
        "gte": 30
      }
    }
  }
}

30分以上遅延したフライトを検索します。

aggs

aggs(Aggregation)は、検索結果に対して集計や統計処理を行うためのトップレベルフィールドです。

単純な検索だけでなく、

  • 航空会社ごとの件数集計
  • 平均チケット価格の算出
  • 日別件数の集計

などを実行できます。

AggregationはElasticsearchの大きな特徴の一つであり、試験でも重要な出題範囲となっています。

参考クエリ

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "carrier_count": {
      "terms": {
        "field": "Carrier"
      }
    }
  }
}

航空会社ごとのフライト件数を集計します。

sort

sort は検索結果の表示順を制御するためのトップレベルフィールドです。

指定しない場合は _score の高い順に結果が返されますが、日時や数値などを基準に並び替えたい場合は sort を利用します。

複数のソート条件を指定することも可能です。

参考クエリ

GET kibana_sample_data_flights/_search
{
  "sort": [
    {
      "AvgTicketPrice": {
        "order": "desc"
      }
    }
  ]
}

チケット価格の高い順に並び替えます。

from

from は検索結果の取得開始位置を指定するためのトップレベルフィールドです。

ページング処理で利用されることが多く、

  • 0件目から取得
  • 10件目から取得
  • 20件目から取得

といった制御が可能です。

通常は size と組み合わせて利用します。

参考クエリ

GET kibana_sample_data_flights/_search
{
  "from": 10
}

11件目以降の検索結果を取得します。

size

size は検索結果として返却するDocument数を指定するためのトップレベルフィールドです。

大量のDocumentが存在する場合でも、必要な件数のみを取得できます。

通常は from と組み合わせて利用し、ページ単位で検索結果を取得します。

参考クエリ

GET kibana_sample_data_flights/_search
{
  "size": 10
}

検索結果を最大10件取得します。

Query DSL全体例

これまで説明したトップレベルフィールドを組み合わせると、以下のようなQuery DSLになります。

GET kibana_sample_data_flights/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "FlightDelay": true
          }
        }
      ],
      "should": [
        {
          "term": {
            "OriginCountry": "US"
          }
        },
        {
          "term": {
            "DestCountry": "US"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "FlightDelayMin": {
              "gte": 30
            }
          }
        },
        {
          "term": {
            "Cancelled": false
          }
        }
      ]
    }
  },
  "aggs": {
    "carrier_count": {
      "terms": {
        "field": "Carrier"
      }
    }
  },
  "sort": [
    {
      "AvgTicketPrice": {
        "order": "desc"
      }
    }
  ],
  "from": 0,
  "size": 10
}

このようにQuery DSLは、リクエスト行と複数のトップレベルフィールドを組み合わせることで、検索・集計・並び替え・ページングを柔軟に実現できます。

Elastic Docs > Explore and analyze > Querying and filtering > Query languages > Query DSL

Elastic Docs > Reference > Elasticsearch > Query languages > Query DSL

Boolクエリ

Boolクエリの基本

ElasticsearchのQuery DSLにおいて、bool クエリ(Boolean Query)は、複数のクエリを論理的に組み合わせるために使用される代表的なクエリの一つです。

bool クエリは、以下4つの句をサポートしており、それぞれの組み合わせによって高度な検索を実現します。

1. must

指定したクエリにすべてマッチしたDocumentのみが検索結果として返されます。AND条件に相当し、結果に必ず含めたい条件を指定するときに利用します。また、must 句に含まれるクエリはスコア計算の対象となります。

2. filter

must と同様にDocumentの絞り込みを行いますが、スコアには影響を与えません。filter句はスコア計算を行わないため、検索条件による絞り込みに適しています。また、条件によっては内部的にキャッシュが利用される場合があります。「検索条件としては必須だが、スコアには影響させたくない」という場合に利用します。

3. should

should句は、条件に一致したDocumentのスコアを高めるために利用されます。また、must句やfilter句が存在しない場合は、OR条件のような動作になります。複数の条件のうち一致したものがある場合、スコアが加算されます。検索結果の優先順位を調整したい場合によく利用されます。

4. must_not

指定した条件に一致するDocumentを検索結果から除外します。NOT条件に相当し、除外条件を定義する際に利用します。boolクエリでは、これらの句を組み合わせることで複雑な検索条件を柔軟に表現できます。

Boolクエリのサンプル 1

以下は kibana_sample_data_flights インデックスに対して、mustshouldfilter を組み合わせた例です。

GET kibana_sample_data_flights/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "FlightDelay": true
          }
        }
      ],
      "should": [
        {
          "term": {
            "OriginCountry": "US"
          }
        },
        {
          "term": {
            "DestCountry": "US"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "FlightDelayMin": {
              "gte": 30
            }
          }
        }
      ]
    }
  }
}

boolクエリの中で、mustshouldfilter を組み合わせています。

1. must句

{
  "term": {
    "FlightDelay": true
  }
}

遅延が発生したフライトのみを検索対象とします。
必須条件であり、スコア計算の対象となります。

2. should句

{
  "term": {
    "OriginCountry": "US"
  }
}
{
  "term": {
    "DestCountry": "US"
  }
}

出発国または到着国がUSのフライトに対してスコアを加算します。
両方に一致する場合はさらにスコアが高くなります。

3. filter句

{
  "range": {
    "FlightDelayMin": {
      "gte": 30
    }
  }
}

30分以上遅延したフライトに限定します。
スコアには影響せず、単純な絞り込み条件として利用されます。

結果として、

  • 遅延が発生している
  • 30分以上の遅延である

という条件を満たしたフライトを検索しつつ、

  • 出発国がUS
  • 到着国がUS

であるフライトのスコアを高くして検索結果を返します。

Boolクエリのサンプル 2

以下は mustmust_not を組み合わせた例です。

GET kibana_sample_data_flights/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "AvgTicketPrice": {
              "gte": 500
            }
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "Cancelled": true
          }
        }
      ]
    }
  }
}

このクエリでは、

  • チケット価格が500ドル以上
  • キャンセルされていない

という条件を満たすフライトを検索します。

must_not に一致したDocumentは検索結果から除外されます。

Boolクエリのサンプル 3

以下は日時フィールドに対して range クエリを利用する例です。

GET kibana_sample_data_flights/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "timestamp": {
              "gte": "2025-01-01T00:00:00",
              "lte": "2025-12-31T23:59:59"
            }
          }
        }
      ]
    }
  }
}

このクエリでは、2025年中のフライトデータのみを検索します。

  • gte :指定値以上
  • lte :指定値以下

を意味します。

日付型フィールドに対する range クエリは、Elastic Certified Engineer Examでもよく利用されるため、必ず理解しておきましょう。

Elastic Docs > Reference > Elasticsearch > Query languages > Query DSL > Compound queries > Boolean

集計 ~Aggregation~

ElasticsearchのAggregationは、大量のDocumentを集計・分析するための機能です。

検索が「どのDocumentを取得するか」を決定する仕組みであるのに対し、Aggregationは、queryに一致したDocument集合に対して集計や分析を実行する仕組みです。

例えば、kibana_sample_data_flights インデックスに対して、

  • 航空会社ごとのフライト件数を知りたい
  • 国ごとの平均チケット価格を知りたい
  • 日別のフライト数の推移を知りたい
  • 日別件数の累積値を知りたい

といった分析を実現できます。

Aggregationは大きく以下の3種類に分類されます。

種類役割
Bucket AggregationDocumentをグループ化する
Metric Aggregation集計値を計算する
Pipeline Aggregation集計結果をさらに加工する

Aggregationを理解する際は、

「Bucketで分類 → Metricで集計 → Pipelineで再計算」

という流れで考えると理解しやすくなります。

Elastic Docs > Explore and analyze > Querying and filtering > Aggregations

Elastic Docs > Reference > Elasticsearch > Aggregations

Aggregationの基本構造

Aggregationは aggs フィールドの中に定義します。

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "aggregation_name": {
      "aggregation_type": {
      }
    }
  }
}

各要素の役割は以下のとおりです。

  • size: 0
    Documentを返さず集計結果のみ取得する
  • aggs
    Aggregation定義
  • aggregation_name
    任意の集計名
  • aggregation_type
    terms、avg、sumなどの集計種類

Bucket Aggregation

Bucket AggregationはDocumentをグループ化するためのAggregationです。
SQLの GROUP BY に近い役割を持ちます。
例えば航空会社ごとのフライト件数を集計する場合は以下のようになります。

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "carrier_count": {
      "terms": {
        "field": "Carrier"
      }
    }
  }
}

このクエリの結果として、以下のようなレスポンスがあります。

CarrierごとにDocumentがグループ化され、件数が表示されています。

代表的なBucket Aggregationは以下の通りです。

Aggregation説明主な用途
termsフィールド値ごとにDocumentをグループ化する航空会社別、国別、カテゴリ別の集計
range指定した数値や日付の範囲ごとにグループ化する価格帯別、遅延時間帯別の集計
date_histogram日時を一定間隔でグループ化する日別、月別、年別の時系列分析
filters複数の条件ごとにグループ化する条件別の件数比較
histogram数値を一定幅の区間ごとにグループ化する距離帯別、価格帯別の分布分析

試験では、terms、date_histogram、avg、sumなどの代表的なAggregationを利用できるようにしておくことが重要です。

Bucket Aggregation サンプル

ここでは、kibana_sample_data_flights インデックスを使って、代表的なBucket Aggregationのサンプルを確認します。Bucket Aggregationは、Documentを特定の条件でグループ化するためのAggregationです。フィールド値、数値範囲、日付間隔、任意条件など、さまざまな切り口でDocumentを分類できます。

terms Aggregation

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "carrier_count": {
      "terms": {
        "field": "Carrier"
      }
    }
  }
}

terms Aggregationは、指定したフィールドの値ごとにDocumentをグループ化します。この例では、Carrier フィールドを使って航空会社ごとのフライト件数を集計しています。カテゴリ別、国別、ステータス別など、keyword型のフィールドを使った件数集計でよく利用されます。

range Aggregation

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "delay_ranges": {
      "range": {
        "field": "FlightDelayMin",
        "ranges": [
          {
            "to": 30
          },
          {
            "from": 30,
            "to": 60
          },
          {
            "from": 60
          }
        ]
      }
    }
  }
}

range Aggregationは、数値や日付を指定した範囲ごとにグループ化します。この例では、FlightDelayMin を使って遅延時間を30分未満、30分以上60分未満、60分以上に分類しています。価格帯、遅延時間、距離など、範囲で分けて分析したい場合に有効です。

date_histogram Aggregation

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "flights_per_day": {
      "date_histogram": {
        "field": "timestamp",
        "calendar_interval": "day"
      }
    }
  }
}

date_histogram Aggregationは、日付型フィールドを一定間隔でグループ化します。この例では、timestamp フィールドを日単位で区切り、日別のフライト件数を集計しています。ログ件数、売上推移、アクセス数など、時系列データを分析する際に頻繁に利用されます。

filters Aggregation

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "flight_status": {
      "filters": {
        "filters": {
          "delayed": {
            "term": {
              "FlightDelay": true
            }
          },
          "on_time": {
            "term": {
              "FlightDelay": false
            }
          },
          "cancelled": {
            "term": {
              "Cancelled": true
            }
          }
        }
      }
    }
  }
}

filters Aggregationは、利用者が定義した複数の条件ごとにDocumentをグループ化します。この例では、遅延便、定刻便、キャンセル便という3つの条件でフライトを分類しています。terms のようにフィールド値で自動分類するのではなく、分析したい条件を明示的に定義できる点が特徴です。

histogram Aggregation

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "ticket_price_histogram": {
      "histogram": {
        "field": "AvgTicketPrice",
        "interval": 100
      }
    }
  }
}

histogram Aggregationは、数値フィールドを一定幅の区間ごとにグループ化します。この例では、AvgTicketPrice を100ドル単位で区切り、価格帯ごとのフライト件数を集計しています。range が任意の範囲を指定するのに対し、histogram は一定間隔で機械的に区切る点が特徴です。

Metric Aggregation

Metric Aggregationは数値の集計値を計算するAggregationです。

例えば平均チケット価格を計算する場合は以下のようになります。

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "average_price": {
      "avg": {
        "field": "AvgTicketPrice"
      }
    }
  }
}

このクエリでは、

平均チケット価格 = 628.41

のような結果を取得できます。

代表的なMetric Aggregationは以下の通りです。

Aggregation説明主な用途
avgフィールドの平均値を計算平均価格、平均応答時間
sumフィールドの合計値を計算売上合計、転送量合計
minフィールドの最小値を取得最安値、最短時間
maxフィールドの最大値を取得最高値、最大遅延
statscount・min・max・avg・sumを一括取得基本統計情報の確認
cardinalityユニークな値の件数を取得利用者数、商品数、航空会社数

Metric Aggregation サンプル

Metric Aggregationは、DocumentやBucketに対して統計値を計算するAggregationです。Bucket Aggregationが「分類」を担当するのに対し、Metric Aggregationは「集計」を担当します。平均値や合計値、最大値、最小値などの統計情報を取得する際に利用されます。

avg Aggregation

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "average_ticket_price": {
      "avg": {
        "field": "AvgTicketPrice"
      }
    }
  }
}

avg Aggregationは指定した数値フィールドの平均値を計算します。この例では、全フライトの平均チケット価格を算出しています。売上分析では平均購入額、監視データでは平均応答時間などの算出によく利用されます。Metric Aggregationの中でも最も利用頻度が高く、試験でも頻出のAggregationです。

sum Aggregation

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "total_distance": {
      "sum": {
        "field": "DistanceKilometers"
      }
    }
  }
}

sum Aggregationは指定したフィールドの合計値を計算します。この例では、全フライトの総飛行距離を算出しています。売上データであれば総売上、ログデータであれば総通信量などを求める際に利用されます。大量データの全体規模を把握するための基本的な集計方法です。

min Aggregation

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "minimum_ticket_price": {
      "min": {
        "field": "AvgTicketPrice"
      }
    }
  }
}

min Aggregationは指定したフィールドの最小値を取得します。この例では、最も安いチケット価格を取得しています。価格分析における最安値の確認や、システム監視における最小応答時間の確認などで利用されます。データの下限値を把握する際に有効です。

max Aggregation

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "maximum_delay": {
      "max": {
        "field": "FlightDelayMin"
      }
    }
  }
}

max Aggregationは指定したフィールドの最大値を取得します。この例では、最も長い遅延時間を取得しています。最大売上、最大レスポンスタイム、最大負荷など、システムや業務におけるピーク値を確認する際に利用されます。異常値や極端なデータを発見する用途でも有効です。

stats Aggregation

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "ticket_price_stats": {
      "stats": {
        "field": "AvgTicketPrice"
      }
    }
  }
}

stats Aggregationは、countminmaxavgsum をまとめて取得するAggregationです。この例ではチケット価格に関する基本統計情報を一度に取得しています。個別にAggregationを定義する必要がなく、対象フィールドの全体像を素早く把握したい場合に便利です。

cardinality Aggregation

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "unique_carriers": {
      "cardinality": {
        "field": "Carrier"
      }
    }
  }
}

cardinality Aggregationは、フィールドに存在するユニークな値の件数を取得します。この例では、何種類の航空会社が存在するかを集計しています。利用者数、商品数、接続元IP数などを求める際によく利用されます。内部的には近似アルゴリズムが利用されるため、大量データでも高速に集計できる点が特徴です。

BucketとMetricの組み合わせ

実運用ではBucketとMetricを組み合わせて利用することが一般的です。

例えば航空会社ごとの平均チケット価格を集計する場合は以下のようになります。

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "by_carrier": {
      "terms": {
        "field": "Carrier"
      },
      "aggs": {
        "avg_price": {
          "avg": {
            "field": "AvgTicketPrice"
          }
        }
      }
    }
  }
}

処理の流れは以下の通りです。

  1. CarrierごとにBucketを作成
  2. 各Bucket内で平均チケット価格を計算

このように、

  • Bucket → 分類
  • Metric → 集計

という組み合わせがAggregationの基本形となります。

Pipeline Aggregation

Pipeline Aggregationは、既存のAggregation結果を利用して新たな集計値を算出するためのAggregationです。

例えば日別フライト数を集計し、その累積値を計算することができます。

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "flights_per_day": {
      "date_histogram": {
        "field": "timestamp",
        "calendar_interval": "day"
      },
      "aggs": {
        "daily_count": {
          "value_count": {
            "field": "FlightNum"
          }
        },
        "cumulative_count": {
          "cumulative_sum": {
            "buckets_path": "daily_count"
          }
        }
      }
    }
  }
}

実行結果

このクエリでは、

  1. date_histogramで日別Bucketを作成
  2. 各日のフライト数を計算
  3. フライト数を累積して算出

という処理が行われます。Pipeline Aggregationは、「Document」ではなく「Aggregation結果」を入力として計算する点が特徴です。

代表的なPipeline Aggregationには以下があります。

Aggregation説明主な用途
cumulative_sum集計値の累積合計を計算累積件数、累積売上
derivative前Bucketとの差分を計算増減数、変化量
moving_fn一定範囲の移動計算を実行移動平均、平滑化
bucket_script複数の集計値から計算比率、割合、KPI算出
bucket_selector条件に合うBucketだけ残す閾値未満のBucket除外

5.8 Pipeline Aggregation サンプル

以下に、Pipeline Aggregationのサンプルクエリを提示します。

cumulative_sum

前のBucketまでの集計値を順次加算し、累積値を算出するPipeline Aggregationです。累積売上や累積件数などの時系列分析で利用されます。

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "flights_per_day": {
      "date_histogram": {
        "field": "timestamp",
        "calendar_interval": "day",
        "order": {
          "_key": "asc"
        }
      },
      "aggs": {
        "daily_flights": {
          "value_count": {
            "field": "FlightNum"
          }
        },
        "cumulative_flights": {
          "cumulative_sum": {
            "buckets_path": "daily_flights"
          }
        }
      }
    }
  }
}

cumulative_sum は、各BucketのMetric Aggregation結果を順番に足し上げ、累積値を計算します。この例では、日別のフライト件数を daily_flights で集計し、その結果をもとに累積フライト件数を算出しています。時系列データで累計値を確認したい場合に有効です。

derivative

前のBucketとの差分を計算するPipeline Aggregationです。増加数や減少数など、時系列データの変化量を分析する際に利用されます。

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "flights_per_day": {
      "date_histogram": {
        "field": "timestamp",
        "calendar_interval": "day",
        "order": {
          "_key": "asc"
        }
      },
      "aggs": {
        "daily_flights": {
          "value_count": {
            "field": "FlightNum"
          }
        },
        "flight_count_diff": {
          "derivative": {
            "buckets_path": "daily_flights"
          }
        }
      }
    }
  }
}

derivative は、前のBucketとの差分を計算するPipeline Aggregationです。この例では、日別フライト件数の前日差を算出しています。前日よりフライト数が増えたか減ったかを確認できるため、時系列データの変化量を分析する場合に有効です。

moving_fn

指定した範囲のBucketを対象に移動平均などの計算を行うPipeline Aggregationです。データの変動を平滑化し、全体的な傾向を把握できます。

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "flights_per_day": {
      "date_histogram": {
        "field": "timestamp",
        "calendar_interval": "day",
        "order": {
          "_key": "asc"
        }
      },
      "aggs": {
        "daily_avg_price": {
          "avg": {
            "field": "AvgTicketPrice"
          }
        },
        "moving_avg_price": {
          "moving_fn": {
            "buckets_path": "daily_avg_price",
            "window": 3,
            "script": "MovingFunctions.unweightedAvg(values)"
          }
        }
      }
    }
  }
}

moving_fn は、指定した範囲のBucketを対象に移動平均などの計算を行うPipeline Aggregationです。この例では、日別の平均チケット価格を計算し、3日間の移動平均を算出しています。日ごとの変動が大きいデータを平滑化し、全体的な傾向を確認したい場合に有効です。

bucket_script

複数のAggregation結果を利用して独自の計算式を実行するPipeline Aggregationです。割合、比率、KPIなどの派生指標を算出できます。

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "by_carrier": {
      "terms": {
        "field": "Carrier"
      },
      "aggs": {
        "total_flights": {
          "value_count": {
            "field": "FlightNum"
          }
        },
        "delayed_flights": {
          "filter": {
            "term": {
              "FlightDelay": true
            }
          },
          "aggs": {
            "delayed_count": {
              "value_count": {
                "field": "FlightNum"
              }
            }
          }
        },
        "delay_rate": {
          "bucket_script": {
            "buckets_path": {
              "total": "total_flights",
              "delayed": "delayed_flights>delayed_count"
            },
            "script": "params.delayed / params.total * 100"
          }
        }
      }
    }
  }
}

bucket_script は、複数のMetric Aggregation結果を使って計算式を実行するPipeline Aggregationです。この例では、航空会社ごとに総フライト数と遅延フライト数を集計し、遅延率を算出しています。割合、比率、KPIのような派生指標を作成する際に利用します。

上記クエリ解説
by_carrierterms Aggregationにより、Carrier ごとにフライトをグループ化します。その各航空会社Bucketの中で、total_flights は全フライト件数を数えます。

一方、delayed_flights では filter Aggregationを使い、FlightDelay: true のDocumentだけに絞り込んでいます。つまり、航空会社ごとのBucket内で、さらに「遅延したフライトだけ」を対象にしたサブBucketを作成しています。

その中で delayed_count により遅延フライト数を数えています。

最後に bucket_script を使い、
[ 遅延率 = 遅延フライト数 / 総フライト数 × 100 ]
を計算しています。

filterを使う意味
ここでの filter は、検索結果全体を絞り込むためではありません。
Carrier ごとのBucket内で、遅延便だけを集計対象にするために使っています。
そのため、このクエリでは、
・航空会社ごとの総フライト数
・航空会社ごとの遅延フライト数
・航空会社ごとの遅延率
を同時に取得できます。

bucket_selector

Aggregation結果に対して条件を適用し、条件を満たすBucketのみを残すPipeline Aggregationです。集計後の絞り込みに利用されます。

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "by_carrier": {
      "terms": {
        "field": "Carrier"
      },
      "aggs": {
        "avg_delay": {
          "avg": {
            "field": "FlightDelayMin"
          }
        },
        "delay_filter": {
          "bucket_selector": {
            "buckets_path": {
              "avgDelay": "avg_delay"
            },
            "script": "params.avgDelay >= 30"
          }
        }
      }
    }
  }
}

bucket_selector は、Metric Aggregationの結果を条件にしてBucketを残すか除外するかを制御するPipeline Aggregationです。この例では、航空会社ごとの平均遅延時間を計算し、平均遅延が30分以上の航空会社だけを結果に残しています。集計後に条件で絞り込みたい場合に有効です。

Aggregationの考え方

Aggregationは以下の順番で考えると理解しやすくなります。

Document
   ↓
Bucket Aggregation
   ↓
Metric Aggregation
   ↓
Pipeline Aggregation

例えば、

フライトデータ
↓
日別にグループ化
↓
各日の件数を集計
↓
累積件数を計算

という流れになります。

以下は、Aggregationに関しての公式Documentです。多くのAggregationが記載されていますが、試験で問われるのは一部です。全てを覚える必要はありません。メインのものを習得し、そうではないものは公式Documentを参照して回答できるようにすればOKです。

SCORE

Elasticsearchでは、検索条件にどの程度一致しているかを表す指標として _score が計算されます。検索結果はデフォルトで _score の高い順に返されるため、より関連性が高いと判断されたDocumentほど上位に表示されます。

Query DSLでは、主に match クエリや bool クエリの mustshould などがスコア計算に利用されます。一方で、filter は絞り込み専用のためスコアには影響しません。

参考クエリ

GET kibana_sample_data_flights/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "FlightDelay": true
          }
        }
      ],
      "should": [
        {
          "term": {
            "OriginCountry": "US"
          }
        },
        {
          "term": {
            "DestCountry": "US"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "FlightDelayMin": {
              "gte": 30
            }
          }
        }
      ]
    }
  }
}

このクエリの動作は以下の通りです。

内容スコアへの影響
must遅延便(FlightDelay=true)であることあり
should出発国または到着国がUSあり
filter遅延時間が30分以上なし

結果として、

  • 遅延便である
  • 30分以上遅延している

という条件を満たすフライトのみが検索対象となります。

そのうえで、

  • 出発国がUS
  • 到着国がUS

に一致するフライトほど _score が高くなり、検索結果の上位に表示されます。

mustfilter はどちらも絞り込みを行いますが、must はスコア計算の対象、filter はスコア計算の対象外という違いがあります。この違いは Bool Query を理解するうえで重要なポイントです。

Elastic社が提供する無料Hands-on Trainingで理解を深めよう

本記事では、Query DSLの基本構造、Bool Query、Aggregation、Scoreの基礎について解説しました。検索や集計の仕組みを本当に理解するためには、実際にクエリを実行しながら学習することが重要です。

Elastic社では、ElasticsearchやKibanaを実際に操作しながら学習できる無料のHands-on TrainingやOn-Demand Trainingを提供しています。これらのトレーニングでは、Query DSLによる検索だけでなく、Aggregation、Kibana、Data View、Dashboardなど、Elastic Stack全体の機能を体験しながら学習できます。

特に本記事で学習したBool QueryやAggregationは、実際にクエリを実行して結果を確認することで理解が深まります。条件を変更した際に検索結果や集計結果がどのように変化するのかを確認しながら学習することをお勧めします。

Elastic Certified Engineer Examでは、Query DSLを理解しているだけでなく、実際にクエリを作成して実行できることが求められます。ぜひHands-on Trainingや自身の検証環境を活用しながら、検索と集計の実践力を高めてください。

Elastic Cloud アカウント作成

Elastic Training

Elastic Learning Portal

試験で問われるポイント

  • Query DSLの基本構造を理解し、検索クエリを実装できること
  • Bool Query(must / should / filter / must_not)を使った条件検索を実装できること
  • Rangeクエリによる数値・日付検索を実装できること
  • 3種類のAggregationの違いを理解し、代表的なAggregationを実装できること
  • Bucket、Metric、Pipelineを組み合わせた集計クエリを実装できること
  • Sort, From, Sizeを理解し、要件に従って実装できること

・問題によっては、クエリを実行しデータを抽出した上で、要件に一致する情報を記入する、というケースもあります。
・内容を覚えていないクエリが出題された場合は、公式Documentの該当箇所を探し、記載されているサンプルのクエリをベースに考えられるようにしておくことを勧めます。