# 画面設計書 13-クエリによる削除

## 概要

本ドキュメントは、OpenSearchのDelete By Query API（`_delete_by_query`）エンドポイントに関する画面設計書である。検索クエリに一致するドキュメントを一括で削除するためのREST APIインターフェースを定義する。

### 本画面の処理概要

本APIは、Query DSLで指定した条件に一致するドキュメントを一括削除する機能を提供する。内部的にはスクロール検索で対象ドキュメントを特定し、バルク削除を実行する。非同期実行やスロットリング制御にも対応している。

**業務上の目的・背景**：大量のドキュメントを条件指定で一括削除する必要がある場合（例：期限切れデータの削除、特定条件のデータクレンジング）、個別のDelete APIを繰り返すのは非効率である。Delete By Query APIにより、1回のリクエストで条件に一致する全ドキュメントを削除でき、バッチ処理の効率化を実現する。

**画面へのアクセス方法**：HTTPクライアントから`POST /{index}/_delete_by_query`エンドポイントにQuery DSLを含むリクエストボディを送信する。

**主要な操作・処理内容**：
1. リクエストボディのQuery DSLを解析し、削除対象ドキュメントを特定するSearchRequestを構築する
2. スクロール検索により対象ドキュメントを段階的に取得する
3. 取得したドキュメントに対してバルク削除操作を実行する
4. バージョンコンフリクト発生時の動作をconflictsパラメータで制御する
5. wait_for_completionがfalseの場合、タスクとして非同期実行し、タスクIDを返却する

**画面遷移**：クエリによる削除スロットル変更（No.14）と連携して実行中タスクのスロットルを変更できる。タスク取得（No.113）やタスクキャンセル（No.114）との連携で非同期タスクの管理が可能。検索（No.21）と同じQuery DSLを使用する。

**権限による表示制御**：対象インデックスに対するdelete権限およびread権限が必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 16 | Delete By Query | 主機能 | クエリに一致するドキュメントを一括削除する主処理 |
| 19 | 全文検索 | 補助機能 | 削除対象ドキュメントを特定するためのクエリ実行 |

## 画面種別

API（条件指定一括削除）

## URL/ルーティング

| メソッド | パス | 説明 |
|---------|------|------|
| POST | `/{index}/_delete_by_query` | 指定インデックスのクエリ一致ドキュメントを削除 |

## 入出力項目

### URLパスパラメータ

| パラメータ | 型 | 必須 | 説明 |
|-----------|------|------|------|
| index | list | はい | 検索対象インデックス名のカンマ区切りリスト。`_all`または空文字で全インデックス |

### クエリパラメータ

| パラメータ | 型 | 必須 | デフォルト | 説明 |
|-----------|------|------|-----------|------|
| analyzer | string | いいえ | - | クエリ文字列のアナライザ |
| analyze_wildcard | boolean | いいえ | false | ワイルドカード・プレフィクスクエリを解析するかどうか |
| default_operator | enum (AND/OR) | いいえ | OR | クエリ文字列クエリのデフォルト演算子 |
| df | string | いいえ | - | フィールドプレフィクスがない場合のデフォルトフィールド |
| from | number | いいえ | 0 | 開始オフセット |
| ignore_unavailable | boolean | いいえ | - | 利用不可のインデックスを無視するかどうか |
| allow_no_indices | boolean | いいえ | - | ワイルドカード表現が具体的なインデックスに解決されない場合に無視するかどうか |
| conflicts | enum (abort/proceed) | いいえ | abort | バージョンコンフリクト時の動作 |
| expand_wildcards | enum | いいえ | open | ワイルドカードの展開方法 |
| lenient | boolean | いいえ | - | 型不一致クエリエラーを無視するかどうか |
| preference | string | いいえ | random | 操作を実行するノードまたはシャードの指定 |
| q | string | いいえ | - | Luceneクエリ文字列構文でのクエリ |
| routing | list | いいえ | - | ルーティング値のカンマ区切りリスト |
| scroll | time | いいえ | - | スクロール検索の一貫性ビュー維持時間 |
| search_type | enum | いいえ | - | 検索操作タイプ |
| search_timeout | time | いいえ | - | 各検索リクエストのタイムアウト |
| max_docs | number | いいえ | 全件 | 処理する最大ドキュメント数 |
| sort | list | いいえ | - | ソート順のカンマ区切りリスト |
| terminate_after | number | いいえ | - | 各シャードで収集する最大ドキュメント数 |
| stats | list | いいえ | - | ログ・統計用のリクエストタグ |
| version | boolean | いいえ | - | ドキュメントバージョンを返すかどうか |
| request_cache | boolean | いいえ | - | リクエストキャッシュの使用 |
| refresh | boolean | いいえ | - | 影響を受けたインデックスをリフレッシュするかどうか |
| timeout | time | いいえ | 1m | 各バルクリクエストのタイムアウト |
| wait_for_active_shards | string | いいえ | 1 | アクティブシャードコピー数の要件 |
| scroll_size | number | いいえ | 100 | スクロール検索のバッチサイズ |
| wait_for_completion | boolean | いいえ | true | リクエストが完了するまでブロックするかどうか |
| requests_per_second | number | いいえ | 0 (無制限) | サブリクエスト/秒のスロットル。-1でスロットルなし |
| slices | number/string | いいえ | 1 | タスクを分割するスライス数。`auto`指定可能 |

### リクエストボディ

| フィールド | 型 | 必須 | 説明 |
|-----------|------|------|------|
| query | object | はい | Query DSLによる削除対象の検索条件 |

## 表示項目

### レスポンスボディ

| フィールド | 型 | 説明 |
|-----------|------|------|
| took | number | 処理にかかった時間（ミリ秒） |
| timed_out | boolean | タイムアウトしたかどうか |
| total | number | 処理されたドキュメントの総数 |
| deleted | number | 削除されたドキュメント数 |
| batches | number | スクロール応答のバッチ数 |
| version_conflicts | number | バージョンコンフリクト数 |
| noops | number | 操作なし（no-op）の数 |
| retries | object | リトライ回数（bulk/search別） |
| throttled_millis | number | スロットリングによる待機時間（ミリ秒） |
| requests_per_second | number | 実際のリクエスト/秒 |
| throttled_until_millis | number | 次のスロットルまでの時間 |
| failures | array | 失敗情報の配列 |

## イベント仕様

### 1-Delete By Queryリクエスト実行

1. `RestDeleteByQueryAction.prepareRequest()`が`doPrepareRequest(request, client, false, false)`を呼び出す（行66-68）
2. `AbstractBulkByQueryRestHandler.parseInternalRequest()`がQuery DSLのパースとSearchRequestの構築を実行する
3. `buildRequest()`でDeleteByQueryRequestを構築し、conflictsとmax_docsを設定する（行71-86）
4. 内部的にスクロール検索で対象ドキュメントを取得し、バルク削除を実行する
5. wait_for_completion=falseの場合、タスクIDを含むレスポンスを即座に返却する

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Delete By Queryリクエスト | Luceneインデックス | SELECT | クエリに一致するドキュメントの検索 |
| Delete By Queryリクエスト | Luceneインデックス | DELETE | 一致したドキュメントの削除 |

### テーブル別更新項目詳細

#### Luceneインデックス

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| DELETE | - | クエリに一致した全ドキュメント | スクロール検索で段階的に処理 |

## メッセージ仕様

| メッセージ種別 | 条件 | メッセージ内容 |
|--------------|------|--------------|
| 成功 | 全件削除成功 | HTTPステータス200、failures配列が空 |
| 部分成功 | 一部コンフリクト（conflicts=proceed） | HTTPステータス200、version_conflicts > 0 |
| エラー | コンフリクト（conflicts=abort） | HTTPステータス409、バージョンコンフリクトエラー |
| 非同期 | wait_for_completion=false | HTTPステータス200、タスクIDを含むレスポンス |

## 例外処理

| 例外 | 条件 | 動作 |
|------|------|------|
| VersionConflictEngineException | conflicts=abortでバージョンコンフリクト | 処理中断、エラーレスポンスを返す |
| IndexNotFoundException | 指定インデックスが存在しない場合 | リクエスト全体が失敗 |
| SearchPhaseExecutionException | 検索フェーズでエラー | リクエスト全体が失敗 |

## 備考

- `conflicts`パラメータの`proceed`設定により、バージョンコンフリクトを無視して処理を継続できる
- `slices`パラメータの`auto`設定により、シャード数に基づいた自動並列化が可能
- `requests_per_second`によるスロットリングはクラスタ負荷の制御に有効
- 内部的にはスクロール検索+バルク削除のパターンで実行されるため、大量データの削除には時間がかかる場合がある

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | delete_by_query.json | `rest-api-spec/src/main/resources/rest-api-spec/api/delete_by_query.json` | API定義。多数のパラメータの型・デフォルト値 |
| 1-2 | DeleteByQueryRequest.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/DeleteByQueryRequest.java` | リクエストデータ構造 |
| 1-3 | BulkByScrollResponse.java | `server/src/main/java/org/opensearch/index/reindex/BulkByScrollResponse.java` | レスポンスデータ構造（共通） |

**読解のコツ**: DeleteByQueryRequestはAbstractBulkByScrollRequestを継承しており、SearchRequestを内包する。検索パラメータとバルク操作パラメータの二層構造に注目。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestDeleteByQueryAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/RestDeleteByQueryAction.java` | RESTハンドラ |
| 2-2 | AbstractBulkByQueryRestHandler.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/AbstractBulkByQueryRestHandler.java` | 共通のリクエスト解析ロジック |

**主要処理フロー**:
1. **RestDeleteByQueryAction行66-68**: prepareRequest()からdoPrepareRequest()を呼び出し（supportsIngestPipeline=false, includeScript=false）
2. **RestDeleteByQueryAction行71-86**: buildRequest()でDeleteByQueryRequestを構築、conflictsとmax_docsのConsumerを設定
3. **AbstractBulkByQueryRestHandler行61-93**: parseInternalRequest()でSearchRequestのパース、scroll_sizeとconflictsの設定

#### Step 3: 親クラスの共通処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AbstractBaseReindexRestHandler.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/AbstractBaseReindexRestHandler.java` | doPrepareRequestの実装 |

**主要処理フロー**:
- requests_per_second、wait_for_completion、scroll等の共通パラメータの処理
- タスク非同期実行の判定とレスポンス構築

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

```
RestDeleteByQueryAction.prepareRequest()                     [行66]
    |
    +-- doPrepareRequest()  (AbstractBaseReindexRestHandler)
            |
            +-- buildRequest()                               [行71]
            |       +-- DeleteByQueryRequest()
            |       +-- parseInternalRequest()               [AbstractBulkByQueryRestHandler行61]
            |               +-- RestSearchAction.parseSearchRequest()
            |               +-- extractRequestSpecificFields()
            |
            +-- NodeClient.execute(DeleteByQueryAction.INSTANCE, ...)
                    |
                    +-- TransportDeleteByQueryAction
                            +-- スクロール検索 + バルク削除
```

### データフロー図

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

HTTPリクエスト              RestDeleteByQueryAction              BulkByScrollResponse
(POST /{index}/         リクエスト解析・構築
 _delete_by_query)              |
   |                            v
   v                  AbstractBulkByQueryRestHandler            レスポンスJSON
Query DSL              SearchRequest構築・パラメータ設定         {took, deleted,
{query:{...}}                   |                                version_conflicts,...}
   |                            v
   v                  TransportDeleteByQueryAction              タスクID
                      スクロール検索→バルク削除                 (非同期時)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| delete_by_query.json | `rest-api-spec/src/main/resources/rest-api-spec/api/delete_by_query.json` | API定義 | REST API仕様 |
| RestDeleteByQueryAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/RestDeleteByQueryAction.java` | ソース | RESTハンドラ |
| AbstractBulkByQueryRestHandler.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/AbstractBulkByQueryRestHandler.java` | ソース | 共通リクエスト解析 |
| AbstractBaseReindexRestHandler.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/AbstractBaseReindexRestHandler.java` | ソース | 共通実行処理 |
| DeleteByQueryRequest.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/DeleteByQueryRequest.java` | ソース | リクエストデータ構造 |
| BulkByScrollResponse.java | `server/src/main/java/org/opensearch/index/reindex/BulkByScrollResponse.java` | ソース | レスポンスデータ構造 |
