# 機能設計書 16-Delete By Query

## 概要

本ドキュメントは、OpenSearchの「Delete By Query」機能の設計を記述する。クエリ条件に一致するドキュメントを一括削除するDelete By Query APIの処理仕様を定義する。

### 本機能の処理概要

本機能は、検索クエリに一致するすべてのドキュメントを一括削除する機能である。REST APIの `POST /{index}/_delete_by_query` エンドポイントを通じて呼び出される。

**業務上の目的・背景**：大量のドキュメントを条件に基づいて一括削除する需要がある。データ保持ポリシーに基づく古いデータの削除、不要データのクリーンアップ、テスト環境のリセット等で利用される。個別のdelete操作を繰り返すよりも効率的にデータを削除できる。

**機能の利用シーン**：期限切れデータの一括削除、条件付きデータクリーンアップ、GDPR対応のデータ削除要求への対処、テストデータの一括削除で利用される。

**主要な処理内容**：
1. ソースインデックスからスクロール検索で対象ドキュメントを順次取得
2. 取得したドキュメントIDに基づくバルク削除操作の実行
3. スロットリングによる負荷制御
4. タスクとしての非同期実行と進捗管理

**関連システム・外部連携**：全文検索機能（対象ドキュメントの特定）、タスク管理機能（非同期実行管理）。

**権限による制御**：アクション名 `indices:data/write/delete/byquery` に基づくセキュリティ権限チェック。対象インデックスへの読み取りおよび書き込み権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 13 | クエリによる削除 | 主機能 | クエリに一致するドキュメントを一括削除する主処理 |
| 14 | クエリによる削除スロットル変更 | 主機能 | Delete By Query操作のリクエスト/秒スロットルを変更する処理 |

## 機能種別

CRUD操作（条件付き一括Delete）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| indices | String[] | Yes | 対象インデックス名（複数可） | 1つ以上必須 |
| searchRequest | SearchRequest | Yes | 削除対象ドキュメントの検索条件 | - |
| maxDocs | int | No | 削除する最大ドキュメント数 | - |
| conflicts | String | No | コンフリクト時の動作（proceed/abort） | - |
| requestsPerSecond | float | No | スロットリング（リクエスト/秒） | - |
| slices | int | No | 並列スライス数 | - |
| scroll | TimeValue | No | スクロールのキープアライブ時間 | - |
| timeout | TimeValue | No | タイムアウト | - |
| waitForCompletion | boolean | No | 同期/非同期実行（デフォルト: true） | - |

### 入力データソース

REST APIリクエスト（HTTP POST、クエリパラメータ + JSONボディ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| took | long | 処理時間（ミリ秒） |
| timed_out | boolean | タイムアウトしたか |
| total | long | 処理対象の総ドキュメント数 |
| deleted | long | 削除されたドキュメント数 |
| version_conflicts | long | バージョンコンフリクト数 |
| batches | int | バッチ処理回数 |
| noops | long | 操作なしの数 |
| retries | Object | リトライ回数（bulk, search） |
| throttled_millis | long | スロットリング待機時間 |
| failures | List | 失敗した操作のリスト |
| task | String | 非同期実行時のタスクID |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信・バリデーション
   └─ 対象インデックスの存在確認、検索クエリの検証
2. タスク登録
   └─ BulkByScrollTaskとして登録
3. スクロール検索で対象ドキュメント取得
   └─ SearchRequestを使用して対象ドキュメントを順次取得
4. バッチ処理ループ
   └─ 取得したドキュメントIDに基づくバルク削除リクエストの実行
5. スロットリング（オプション）
   └─ requestsPerSecondに基づく待機
6. 完了・レスポンス返却
   └─ BulkByScrollResponse生成
```

### フローチャート

```mermaid
flowchart TD
    A[Delete By Query リクエスト] --> B{バリデーション OK?}
    B -->|No| C[エラー返却]
    B -->|Yes| D[タスク登録]
    D --> E[スクロール検索開始]
    E --> F{ドキュメントあり?}
    F -->|No| G[完了]
    F -->|Yes| H[バルク削除実行]
    H --> I{スロットリング?}
    I -->|Yes| J[待機]
    I -->|No| E
    J --> E
    G --> K[BulkByScrollResponse 返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-16-01 | スナップショット整合性 | スクロール検索時点のスナップショットに基づいて削除対象が決定される。処理中に新規追加されたドキュメントは対象外 | 常時 |
| BR-16-02 | バージョンコンフリクト | 削除対象ドキュメントが処理中に変更された場合のコンフリクト処理 | 常時 |
| BR-16-03 | 部分的成功 | 全体としてアトミックではなく、一部が失敗しても処理は継続可能（conflicts=proceed時） | conflicts=proceed |

### 計算ロジック

BulkByScrollResponseのdeletedカウンタは各バッチ処理の削除成功数を累積して算出される。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 対象検索 | Lucene Index | SELECT | スクロール検索による削除対象ドキュメントの取得 |
| ドキュメント削除 | Lucene Index | DELETE | バルク操作によるドキュメント削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | ActionRequestValidationException | 対象インデックス未指定 | インデックスを指定 |
| 409 | VersionConflictEngineException | バージョンコンフリクト | conflicts=proceedに設定 |
| 408 | タイムアウト | 処理がタイムアウト | タイムアウト値を増加 |

### リトライ仕様

バルク削除とスクロール検索にそれぞれリトライメカニズムが備わっている。

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

Delete By Query全体はアトミックではない。バッチ単位で処理される。

## パフォーマンス要件

- slicesパラメータによる並列化でスループット向上が可能
- requestsPerSecondによるスロットリングで負荷制御
- 大量削除時はインデックスの削除と再作成の方が効率的な場合がある

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

- 対象インデックスへのread/write両方の権限が必要
- アクション名 `indices:data/write/delete/byquery` に対する権限チェック

## 備考

- TransportDeleteByQueryActionはClient, ScriptService, ClusterService, TransportSearchActionに依存
- Update By Queryと同じ基底クラス（AbstractAsyncBulkByScrollAction）を共有するが、スクリプト適用は行わず削除のみを実行
- AsyncDeleteByQueryActionが実際の非同期削除ロジックを実装

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DeleteByQueryRequest.java | `server/src/main/java/org/opensearch/index/reindex/DeleteByQueryRequest.java` | リクエスト構造。AbstractBulkByScrollRequestを継承 |
| 1-2 | BulkByScrollResponse.java | `server/src/main/java/org/opensearch/index/reindex/BulkByScrollResponse.java` | 共通レスポンス構造 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | DeleteByQueryAction.java | `server/src/main/java/org/opensearch/index/reindex/DeleteByQueryAction.java` | アクション名 `indices:data/write/delete/byquery` の定義 |
| 2-2 | TransportDeleteByQueryAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/TransportDeleteByQueryAction.java` | トランスポート処理 |

**主要処理フロー**:
1. **42-45行目（DeleteByQueryAction）**: アクション名定義
2. **51-53行目（TransportDeleteByQueryAction）**: HandledTransportActionを継承、TransportIndicesResolvingActionを実装
3. **55-59行目**: ThreadPool, Client, ScriptService, ClusterService, TransportSearchActionへの依存

#### Step 3: 実処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AsyncDeleteByQueryAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/AsyncDeleteByQueryAction.java` | 非同期削除の実装 |
| 3-2 | AbstractAsyncBulkByScrollAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/AbstractAsyncBulkByScrollAction.java` | 共通スクロール+バルク処理 |

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

```
REST API (POST /{index}/_delete_by_query)
    |
    +-- TransportDeleteByQueryAction
           |
           +-- AsyncDeleteByQueryAction
                  |
                  +-- AbstractAsyncBulkByScrollAction
                         |
                         +-- ScrollableHitSource (スクロール検索)
                         |      └─ ClientScrollableHitSource
                         |
                         +-- BulkRequest (バルク削除)
```

### データフロー図

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

DeleteByQueryRequest     -->  TransportDeleteByQueryAction      -->  BulkByScrollResponse
 - indices                     |                                      - took
 - searchRequest               +-> AsyncDeleteByQueryAction           - total
 - requestsPerSecond            |                                     - deleted
 - slices                       +-> スクロール検索                     - failures
                                +-> バルク削除
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| DeleteByQueryAction.java | `server/src/main/java/org/opensearch/index/reindex/DeleteByQueryAction.java` | ソース | アクション型定義 |
| DeleteByQueryRequest.java | `server/src/main/java/org/opensearch/index/reindex/DeleteByQueryRequest.java` | ソース | リクエスト構造 |
| DeleteByQueryRequestBuilder.java | `server/src/main/java/org/opensearch/index/reindex/DeleteByQueryRequestBuilder.java` | ソース | リクエストビルダー |
| TransportDeleteByQueryAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/TransportDeleteByQueryAction.java` | ソース | トランスポート処理 |
| AsyncDeleteByQueryAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/AsyncDeleteByQueryAction.java` | ソース | 非同期削除ロジック |
| RestDeleteByQueryAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/RestDeleteByQueryAction.java` | ソース | REST APIハンドラー |
| AbstractAsyncBulkByScrollAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/AbstractAsyncBulkByScrollAction.java` | ソース | 共通処理 |
| BulkByScrollResponse.java | `server/src/main/java/org/opensearch/index/reindex/BulkByScrollResponse.java` | ソース | レスポンス |
| BulkByScrollTask.java | `server/src/main/java/org/opensearch/index/reindex/BulkByScrollTask.java` | ソース | タスク管理 |
