【データ分析】Elasticsearchのパイプクエリ言語ESQL

## はじめに
Elasticsearchは、新しいクエリ言語であるES|QL（Elasticsearch Query Language）の一般公開を発表しました。この記事では、ES|QLの機能と利点、そしてその導入による新しいデータ調査の可能性について詳しく紹介します。

[デモサイト](https://esql.demo.elastic.co/)

## ES|QLとは何か？
ES|QLは、データ調査を簡素化し、効率化するために設計された動的なクエリ言語です。従来のQueryDSLに代わり、シンプルで直感的なクエリ構文を提供し、データソースや構造に関係なく迅速なデータ検索を可能にします。特にパイプド構文により、複数の操作を連鎖させることで、複雑なデータ調査も簡単に行うことができます。

### ES|QLの例
以下は、典型的なES|QLクエリの例です：

```sql
FROM logs-system.auth*
| WHERE host.os.type == "linux"
  AND event.outcome == "success"
  AND system.auth.ssh.event == "Accepted"
  AND (user.name IS NOT NULL
       AND source.ip IS NOT NULL
       AND source.port IS NOT NULL
       AND system.auth.ssh.method IS NOT NULL)
| STATS auth_count = COUNT(*) BY user.name, source.ip,
  source.port, system.auth.ssh.method
| SORT auth_count DESC
```

このクエリは、Linuxホスト上で成功したSSH認証イベントをフィルタリングし、ユーザー名、ソースIP、ソースポート、およびSSHメソッドごとに認証の回数をカウントします。その結果を認証回数で降順に並べ替えます。このように、ES|QLは直感的な構文で複雑なクエリを作成できるため、ユーザーは容易に高度なデータ分析を行うことができます。

## ES|QLの主な機能と利点
### 高度な検索機能
ES|QLは、新しいクエリエンジンにより並行処理を強化し、検索速度を大幅に向上させます。これにより、大規模なデータセットに対しても迅速な検索が可能となります。並行処理により、複数のクエリを同時に実行することができ、効率的なデータ処理が実現されます。

### Kibanaとの統合
ES|QLはKibanaと完全に統合されており、データの可視化と分析を一つの画面で行うことができます。Kibanaのインターフェース内でES|QLクエリを作成し、リアルタイムで結果を確認することができます。また、クエリ履歴機能により、過去のクエリを簡単に再実行することも可能です。これにより、ユーザーは効果的にデータの調査を進めることができます。

### 非同期クエリのサポート
ES|QLは非同期クエリをサポートしており、長時間実行されるクエリを非同期で実行し、結果が準備できたときに取得できます。これにより、リソース管理が最適化され、より効率的なクエリプロセスが実現します。非同期クエリの例として、以下のようなクエリがあります：

```shell
POST /_query/async
{
  "query": """
    FROM library
    | STATS MAX(page_count) BY year = BUCKET(release_date, 1 year)
    | SORT year
    | LIMIT 5
  """,
  "wait_for_completion_timeout": "2s"
}
```

このクエリは、ライブラリデータベースから最大ページ数を年ごとに集計し、結果をソートして上位5件を取得します。wait_for_completion_timeoutパラメータを使用することで、クエリ結果を非同期に取得することができます。

## 技術的な詳細と改善点
### 新しいクエリエンジン
ES|QLは、新しい専用のクエリエンジンにより、パフォーマンスが大幅に向上しています。このクエリエンジンは、コアおよびノード全体で並行処理を行い、多様なデータソースや構造にわたるシームレスなクエリを提供します。各ES|QLクエリは、Query DSLへの変換やトランスパイルを必要とせず、直接解析され、実行計画に最適化されて、データを保持する関連ノードで並行して実行されます。これにより、ユーザーは箱から出してすぐに利用できる高速なクエリを得ることができます。

また、メモリ管理が強化されており、リソース集中的なクエリ中のメモリ使用量を厳密に監視するためのメモリトラッキング機能が追加されています。これにより、負荷がかかっている場合でも安定した動作を維持することができます。

### 日付時間フィルタリングのサポート
ES|QLは、日付時間フィルタリングのサポートを強化し、クエリ構築をより直感的かつ効率的に行えるようになりました。以下のクエリ例では、現在から1年1ヶ月1週間以内のデータをフィルタリングしています：

```sql
FROM index
| WHERE @timestamp > now() - 1 year + 1 month + 1 week
```

このように、ES|QLは日付時間の計算を簡単に行うことができ、ユーザーは複雑な時間範囲のフィルタリングをシンプルな構文で記述することができます。

### クロスクラスタ検索のサポート
技術プレビューとして、クロスクラスタ検索機能も提供されており、複数のElasticsearchクラスターにまたがるデータを統一的にクエリできます。これにより、ユーザーは異なるクラスターにあるデータをシームレスに検索し、統合された視点で分析することができます。以下はその例です：

```sql
FROM cluster_one:my-index-000001
| LIMIT 10
```

このクエリは、リモートクラスター「cluster_one」にある「my-index-000001」からデータを取得します。このようにして、ユーザーは複数のクラスターに分散されたデータを統一的に扱うことができ、広範なデータ分析が可能になります。

## 実際の使用例と応用
### セキュリティとオブザーバビリティ
ES|QLは、セキュリティインシデントの調査やオブザーバビリティデータの分析に非常に有効です。具体的なユースケースとして、セキュリティログの調査やシステムの稼働状況の監視などが挙げられます。例えば、特定のホスト上での成功したSSH認証イベントを調査する場合、以下のようなクエリを使用することができます：

```sql
FROM logs-system.auth*
| WHERE host.os.type == "linux"
  AND event.outcome == "success"
  AND system.auth.ssh.event == "Accepted"
  AND (user.name IS NOT NULL
       AND source.ip IS NOT NULL
       AND source.port IS NOT NULL
       AND system.auth.ssh.method IS NOT NULL)
| STATS auth_count = COUNT(*) BY user.name, source.ip,
  source.port, system.auth.ssh.method
| SORT auth_count DESC
```

このクエリにより、Linuxホスト上で成功したSSH認証イベントの詳細を簡単に取得できます。

### リトリーバル・オーグメンテッド・ジェネレーション（RAG）
RAGとの統合により、ES|QLはAI/MLを活用した高度な情報検索も可能にします。例えば、特定のキーワードに基づく文書の検索や、画像ベクトルによる類似画像の検索などが挙げられます。将来的には、さらに多くの機能が追加される予定です。

以下の例は、指定されたキーワードと画像ベクトルに基づいて最も人気のある画像を取得するクエリです：

```sql
SEARCH images [
  | WHERE date > now() - 1 month
  | RANK MATCH "mountain lake"
  | WHERE _score > 0.1
 

 | LIMIT 100
  | RANK KNN image user_image_vector K 10
]
| STATS c = COUNT(votes) BY rating
| LIMIT 5
```

このクエリは、特定のキーワードを含む画像を検索し、その人気度に基づいて上位5件の結果を取得します。

### ES|QLクエリ履歴
ES|QLは、ユーザーが過去のクエリを簡単に再実行できるようにするクエリ履歴機能を提供します。これにより、同じクエリを繰り返し実行する手間が省け、効率的に作業を進めることができます。Kibanaのインターフェース内で、最近実行したクエリのリストを表示し、選択するだけで再実行できます。

![クエリ履歴.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/26230e14-53d6-3128-f706-49fcf6a9c9fe.png)

### ハイブリッドプランニングと動的データ削減
ES|QLは、大規模なElasticsearchデプロイメントにおいても一貫したパフォーマンスを提供するために、ハイブリッドプランニングと動的データ削減を導入しています。クエリ実行の際、コーディネーティングノードはグローバルなデータビューに基づいてグローバルプランニングを行い、そのプランをすべてのデータノードにブロードキャストします。各ノードは、実際のストレージ統計に基づいてプランをローカルに調整し、クエリを実行します。これにより、クエリ実行の効率が向上し、大規模なデータセットに対しても迅速な応答を実現します。

![ハイブリッド計画と動的データ削減.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/2f2104e4-86ff-cf8a-4663-2cb7578fce52.png)
例えば、スキーマの進化に伴うスパースマッピングの初期フィルター評価など、動的データ削減技術は、シャード間のI/Oトラフィックを最小限に抑え、クエリ実行中のLuceneリーダーのオープン時間を短縮することができます。

### ネイティブES|QLクライアント
ES|QLは、_query RESTエンドポイントを通じて普遍的に利用できますが、今後、さまざまな人気言語でネイティブにES|QLをアクセスするためのリッチなAPIも提供される予定です。現在、Elasticsearchクライアントを通じてES|QLの結果をJavaやPHPのオブジェクトとして扱ったり、Pythonのデータフレームとして操作したりすることができます。Jupyterユーザー向けには、専用のスタートガイドノートブックも用意されています。

![ネイティブ ES|QL クライアント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/e32cf1d0-1a03-8256-c0e8-17b5305c7cb2.png)

これにより、ES|QLはさまざまなプログラミング言語や環境での利用が可能となり、ユーザーは自分の得意な言語でES|QLを活用することができます。

## 実際の使用例と応用 (続き)
### 時系列データ、メトリクス、およびオブザーバビリティ
Elasticsearchは、時系列データストリーム（TSDS）を通じて、メトリクスの専用ソリューションを提供しています。この概念により、特殊なタイプとルーティングを使用してディスクストレージを最大70％削減できます。ES|QLは、この機能を最大限に活用し、メトリクスデータの分析を簡素化します。

以下はその例です：

```sql
METRICS pods load=avg(cpu), writes=max(rate(indexing_requests)) BY pod
| SORT pod
```

このクエリは、各ポッドごとのCPUの平均負荷とインデックス要求の最大書き込みレートを計算し、ポッドごとにソートします。

### インライン統計
ES|QLのSTATSコマンドは、統計の要約に非常に有用ですが、データの元のコンテキストを失うことなく集計を行うことは困難でした。この課題に対処するために、インライン統計（INLINESTATS）機能が導入されました。これにより、各グループ内で統計を計算し、元のデータセットに結果を統合できます。

以下はその例です：

```sql
FROM shop
| INLINESTATS avg_price = AVG(price) BY category
```

このクエリは、各カテゴリごとに平均価格を計算し、元のデータセットに「avg_price」列として追加します。

## まとめ
ES|QLの登場により、Elasticsearchユーザーはデータ調査をより簡単に、迅速に行うことができるようになりました。新しいクエリエンジン、強化された日付時間フィルタリング、クロスクラスタ検索のサポートなど、多くの機能が追加され、ユーザーのデータ分析体験が大幅に向上します。今後の発展に期待しつつ、ES|QLを活用したデータ調査の実践をぜひお試しください。

<font color="Gray">※画像やコードは以下のサイトより引用しています。<br>https://www.elastic.co/search-labs/blog/esql-piped-query-language-goes-ga</font>

## 参考リンク
- [Elasticsearch公式ブログ](https://www.elastic.co/search-labs/blog/esql-piped-query-language-goes-ga)
- [デモサイト](https://esql.demo.elastic.co/)
- [ES|QLクエリをTypeScriptの型に](https://www.elastic.co/search-labs/blog/esql-javascript-helper-typescript)
- [街を旅する：LLMとElasticsearchでシンプルになった地理空間検索](https://www.elastic.co/search-labs/blog/geospatial-search-llm-elasticsearch)

Qiita内で公開されているElasticSearch関連サイトです。
- [はじめての Elasticsearch](https://qiita.com/nskydiving/items/1c2dc4e0b9c98d164329)
Elasticsearchのインストールと基本的な操作方法を解説する入門チュートリアルの内容です
- [今のデータが知りたい！に応えるPythonでのリアルタイム処理基盤の構築をざっと振り返る](https://qiita.com/okiyuki99/items/eb0410e0090e18c662e0)
PythonとOSSを用いたリアルタイムデータ処理基盤の構築とその実践事例が紹介されています。
- [ElasticsearchとNeo4jをKafkaで連携する](https://qiita.com/caunu-s/items/9acc77175ee69bdd9a3e)
ElasticsearchとNeo4jをKafkaで連携し、データの検索と関連性の可視化を実現する方法を解説