# 機能設計書 28-Validate API

## 概要

本ドキュメントは、OpenSearchのValidate API機能に関する機能設計書である。検索クエリの構文妥当性を事前検証する機能を定義する。

### 本機能の処理概要

**業務上の目的・背景**：検索クエリを実行する前に、クエリの構文が正しいかどうかを確認したい場合がある。特に複雑なクエリを構築する際やユーザー入力ベースのクエリを動的に生成する場合、実行前のバリデーションにより不正なクエリによるエラーを事前に検出できる。Validate APIはクエリを実際に実行せずに構文チェックのみを行い、オプションでクエリの書き換え結果や説明も返却する。

**機能の利用シーン**：動的に構築されたクエリの事前検証、クエリビルダーUIでのリアルタイムバリデーション、バッチ処理前のクエリ構文確認、クエリのデバッグ（explain/rewriteオプション）などで利用される。

**主要な処理内容**：
1. ValidateQueryRequestを受信し、クエリをリライトする
2. ブロードキャストアクションとして各シャードにバリデーションリクエストを送信する
3. 各シャードでSearchContextを作成し、クエリの解析・検証を実行する
4. explain/rewriteオプション指定時はクエリの書き換え結果や説明を返却する
5. 全シャードの結果を集約してバリデーション結果を返却する

**関連システム・外部連携**：SearchServiceのcreateValidationContext()を使用して検証用コンテキストを作成する。

**権限による制御**：`indices:admin/validate/query`アクション名で権限が制御される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 31 | クエリバリデーション | 主画面 | 検索クエリの構文妥当性を事前検証する処理 |

## 機能種別

バリデーション（クエリ構文検証）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| indices | String[] | No | 対象インデックス名 | - |
| query | QueryBuilder | No | 検証対象のクエリ（デフォルト: match_all） | - |
| explain | boolean | No | クエリの説明を返却するか | デフォルト: false |
| rewrite | boolean | No | リライト後のクエリを返却するか | デフォルト: false |
| all_shards | boolean | No | 全シャードで検証するか | デフォルト: false |
| indices_options | IndicesOptions | No | インデックス解決オプション | - |

### 入力データソース

REST APIエンドポイント（`GET /{index}/_validate/query`, `POST /{index}/_validate/query`）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| valid | boolean | クエリが有効かどうか |
| _shards | ShardStatistics | シャード実行統計 |
| explanations | QueryExplanation[] | クエリの説明（explain/rewrite指定時） |
| explanations[].index | String | インデックス名 |
| explanations[].shard | int | シャード番号 |
| explanations[].valid | boolean | そのシャードでの有効性 |
| explanations[].explanation | String | クエリの説明テキスト |
| explanations[].error | String | エラーメッセージ |

### 出力先

REST APIレスポンス（JSON形式）

## 処理フロー

### 処理シーケンス

```
1. クエリのリライト
   └─ Rewriteable.rewriteAndFetchでクエリを最適化
2. シャードルーティング
   └─ all_shards=falseの場合はランダムルーティングで単一シャードに限定
3. 各シャードでのバリデーション実行
   └─ searchService.createValidationContextで検証コンテキスト作成
   └─ toQuery()でクエリ変換、preProcess()で前処理
4. 結果の集約
   └─ 全シャードのvalid判定を論理AND、explanationsを収集
5. ValidateQueryResponseとして返却
```

### フローチャート

```mermaid
flowchart TD
    A[ValidateQueryRequest] --> B[クエリリライト]
    B --> C{リライトエラー?}
    C -->|Yes| D[valid=false, error付きレスポンス]
    C -->|No| E{all_shards?}
    E -->|No| F[ランダムルーティングで単一シャード選択]
    E -->|Yes| G[全シャードを対象]
    F --> H[各シャードでshardOperation実行]
    G --> H
    H --> I[createValidationContext]
    I --> J[toQuery + preProcess]
    J --> K{QueryShardException?}
    K -->|Yes| L[valid=false, error=詳細メッセージ]
    K -->|No| M[valid=true, explanation=クエリ文字列]
    L --> N[結果集約]
    M --> N
    N --> O[ValidateQueryResponse返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-28-01 | デフォルトクエリ | queryが未指定の場合、MatchAllQueryBuilderが使用される | query未指定時 |
| BR-28-02 | 単一シャード最適化 | all_shards=falseの場合、ランダムルーティングで単一シャードのみ検証 | all_shards=false |
| BR-28-03 | valid判定 | 全シャードの結果のANDで最終的なvalid値を決定 | 常時 |
| BR-28-04 | rewriteオプション | rewrite=trueの場合、MatchNoDocsQueryの場合は元のクエリ文字列を返却 | rewrite=true |

### 計算ロジック

特になし。

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| バリデーション | 対象インデックスのマッピング | メタデータ参照 | クエリの構文検証のためにマッピング情報を参照 |

### テーブル別操作詳細

読み取り専用のメタデータ参照操作。実際のデータ検索は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 200 | valid=false | クエリ構文エラー（QueryShardException/ParsingException） | エラーメッセージを確認しクエリを修正 |
| 404 | IndexNotFoundException | 指定インデックスが存在しない | インデックス名を確認 |
| 500 | ClusterBlockException | クラスタがREADブロック状態 | クラスタ状態を確認 |

### リトライ仕様

BroadcastActionのリトライ仕様に準拠。

## トランザクション仕様

読み取り専用のバリデーション操作であり、トランザクション管理は不要。

## パフォーマンス要件

- SEARCHスレッドプールで実行される
- all_shards=falseの場合は単一シャードのみ検証するため、高速に応答

## セキュリティ考慮事項

- アクション名`indices:admin/validate/query`による権限制御
- READレベルのクラスタブロックチェック

## 備考

- TransportBroadcastActionを継承しており、ブロードキャスト形式でシャードに送信される
- query未指定時はMatchAllQueryが使用される

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ValidateQueryRequest.java | `server/src/main/java/org/opensearch/action/admin/indices/validate/query/ValidateQueryRequest.java` | query, explain, rewrite, allShardsフィールド |
| 1-2 | ValidateQueryResponse.java | `server/src/main/java/org/opensearch/action/admin/indices/validate/query/ValidateQueryResponse.java` | valid判定、queryExplanationsリスト |
| 1-3 | QueryExplanation.java | `server/src/main/java/org/opensearch/action/admin/indices/validate/query/QueryExplanation.java` | クエリ説明の構造体 |

**読解のコツ**: ValidateQueryRequestの62行目でデフォルトクエリとしてMatchAllQueryBuilderが設定されている。explain/rewrite/allShardsのbooleanフラグ（64-66行目）が出力内容を制御する。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ValidateQueryAction.java | `server/src/main/java/org/opensearch/action/admin/indices/validate/query/ValidateQueryAction.java` | アクション定義 |

#### Step 3: トランスポート層の処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TransportValidateQueryAction.java | `server/src/main/java/org/opensearch/action/admin/indices/validate/query/TransportValidateQueryAction.java` | バリデーション実行の中核 |

**主要処理フロー**:
- **110-141行目**: doExecute - クエリリライト、IndexNotFoundExceptionの特別処理
- **144-149行目**: newShardRequest - エイリアスフィルタ付きシャードリクエスト構築
- **157-167行目**: shards - all_shardsフラグによるルーティング制御（ランダムor全シャード）
- **180-221行目**: newResponse - シャード結果の集約、valid判定、explanations収集
- **224-251行目**: shardOperation - 検証コンテキスト作成、toQuery、preProcess実行
- **253-260行目**: explain - rewriteオプション対応のクエリ説明生成

### プログラム呼び出し階層図

```
REST (/_validate/query)
    |
    +-- TransportValidateQueryAction.doExecute()
            |
            +-- Rewriteable.rewriteAndFetch() [クエリリライト]
            |
            +-- shards() [シャードルーティング解決]
            |       |
            |       +-- all_shards=false: ランダムルーティング
            |       +-- all_shards=true: 全シャード
            |
            +-- shardOperation() [各シャード]
            |       |
            |       +-- searchService.createValidationContext()
            |       +-- toQuery() [クエリ変換]
            |       +-- preProcess() [前処理]
            |       +-- explain() [説明生成]
            |
            +-- newResponse() [結果集約]
```

### データフロー図

```
[入力]                    [処理]                        [出力]

ValidateQueryRequest ──> リライト ──────> ValidateQueryResponse
  (indices, query,        |                (valid,
   explain, rewrite,  ブロードキャスト       explanations[])
   all_shards)           |
                    各シャードで検証
                         |
                    結果集約 (AND)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ValidateQueryAction.java | `server/src/main/java/org/opensearch/action/admin/indices/validate/query/ValidateQueryAction.java` | ソース | アクション型定義 |
| ValidateQueryRequest.java | `server/src/main/java/org/opensearch/action/admin/indices/validate/query/ValidateQueryRequest.java` | ソース | リクエストモデル |
| ValidateQueryResponse.java | `server/src/main/java/org/opensearch/action/admin/indices/validate/query/ValidateQueryResponse.java` | ソース | レスポンスモデル |
| TransportValidateQueryAction.java | `server/src/main/java/org/opensearch/action/admin/indices/validate/query/TransportValidateQueryAction.java` | ソース | バリデーション実行ロジック |
| ShardValidateQueryRequest.java | `server/src/main/java/org/opensearch/action/admin/indices/validate/query/ShardValidateQueryRequest.java` | ソース | シャードレベルリクエスト |
| ShardValidateQueryResponse.java | `server/src/main/java/org/opensearch/action/admin/indices/validate/query/ShardValidateQueryResponse.java` | ソース | シャードレベルレスポンス |
| QueryExplanation.java | `server/src/main/java/org/opensearch/action/admin/indices/validate/query/QueryExplanation.java` | ソース | クエリ説明構造体 |
