# 画面設計書 12-バルク操作

## 概要

本ドキュメントは、OpenSearchのBulk API（`_bulk`）エンドポイントに関する画面設計書である。1回のリクエストで複数のindex/update/delete操作を一括実行するためのREST APIインターフェースを定義する。

### 本画面の処理概要

本APIは、複数のドキュメント操作（登録・更新・削除）を1回のHTTPリクエストで一括実行する機能を提供する。NDJSON（Newline Delimited JSON）形式のリクエストボディにより、異なるインデックスに対する異なる操作を混在させて実行できる。

**業務上の目的・背景**：大量のドキュメントを効率的に処理するために、個別のAPI呼び出しではなく一括操作が不可欠である。データインポート、ログ収集、ETL処理など、大量データの投入・更新シナリオにおいて、Bulk APIはネットワークオーバーヘッドを最小化し、スループットを最大化する。インジェストパイプラインの適用もサポートしており、データ変換を伴う一括投入にも対応する。

**画面へのアクセス方法**：HTTPクライアントから`POST /_bulk`または`PUT /_bulk`、`POST /{index}/_bulk`または`PUT /{index}/_bulk`エンドポイントにNDJSON形式のリクエストボディを送信する。

**主要な操作・処理内容**：
1. NDJSON形式のリクエストボディを解析し、アクション行（index/create/update/delete）とデータ行のペアを抽出する
2. 各操作についてインデックス名解決、ルーティング計算、インジェストパイプライン適用を実行する
3. シャードごとに操作をグループ化し、各シャードに対してバルクシャードリクエストを実行する
4. 各シャードからの応答を集約し、操作ごとの成否をレスポンスとして構築する

**画面遷移**：ドキュメント登録・更新（No.3）、ドキュメント作成（No.4）、ドキュメント更新（No.10）、ドキュメント削除（No.9）の各操作を一括で実行できる。検索（No.21）のための大量データ投入に使用されることが多い。

**権限による表示制御**：各操作の対象インデックスに対するindex/delete権限が必要。インジェストパイプラインを使用する場合は、パイプラインの実行権限も必要となる。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 13 | バルク操作 | 主機能 | 複数のindex/update/delete操作を一括実行する主処理 |
| 36 | インジェストパイプライン | 補助機能 | バルク操作時のインジェストパイプライン適用処理 |

## 画面種別

API（複数ドキュメント一括操作）

## URL/ルーティング

| メソッド | パス | 説明 |
|---------|------|------|
| POST/PUT | `/_bulk` | インデックス指定なし（ボディ内で個別指定） |
| POST/PUT | `/{index}/_bulk` | デフォルトインデックスを指定 |

## 入出力項目

### URLパスパラメータ

| パラメータ | 型 | 必須 | 説明 |
|-----------|------|------|------|
| index | string | いいえ | アイテムがインデックスを指定しない場合のデフォルトインデックス名 |

### クエリパラメータ

| パラメータ | 型 | 必須 | デフォルト | 説明 |
|-----------|------|------|-----------|------|
| wait_for_active_shards | string | いいえ | 1 | 操作を実行する前にアクティブであるべきシャードコピーの数 |
| refresh | enum (true/false/wait_for) | いいえ | false | 影響を受けたシャードのリフレッシュポリシー |
| routing | string | いいえ | - | 特定のルーティング値 |
| timeout | time | いいえ | 1m | 明示的な操作タイムアウト |
| type | string | いいえ | - | デフォルトのドキュメントタイプ（非推奨） |
| _source | list | いいえ | - | _sourceフィールドの返却設定 |
| _source_excludes | list | いいえ | - | _sourceフィールドから除外するフィールドのリスト |
| _source_includes | list | いいえ | - | _sourceフィールドから抽出して返すフィールドのリスト |
| pipeline | string | いいえ | - | 受信ドキュメントの前処理に使用するパイプラインID |
| require_alias | boolean | いいえ | false | 全ドキュメントにrequire_aliasを設定 |
| batch_size | int | いいえ | - | バッチサイズの設定 |

### リクエストボディ（NDJSON形式）

各操作は2行（deleteは1行）のペアで構成される。

| 行 | 説明 | 例 |
|----|------|-----|
| アクション行 | 操作種別と対象を指定 | `{"index":{"_index":"test","_id":"1"}}` |
| データ行 | ドキュメントデータ（deleteの場合不要） | `{"field1":"value1"}` |

サポートされるアクション：`index`, `create`, `update`, `delete`

## 表示項目

### レスポンスボディ

| フィールド | 型 | 説明 |
|-----------|------|------|
| took | number | 処理にかかった時間（ミリ秒） |
| errors | boolean | いずれかの操作でエラーが発生したかどうか |
| items | array | 各操作の結果の配列（リクエスト順） |
| items[].index/_index | string | 対象インデックス名 |
| items[].index/_id | string | ドキュメントID |
| items[].index/_version | number | ドキュメントバージョン |
| items[].index/result | string | 操作結果（created/updated/deleted等） |
| items[].index/status | number | HTTPステータスコード |
| items[].index/error | object | エラーが発生した場合のエラー情報 |

## イベント仕様

### 1-バルクリクエスト実行

クライアントからBulkリクエストを受信すると、以下の処理が実行される。

1. `RestBulkAction.prepareRequest()`がリクエストパラメータを解析し、`BulkRequest`オブジェクトを構築する（行87-112）
2. NDJSON形式のボディを`BulkRequest.add()`で解析し、各操作をDocWriteRequestとして格納する（行100-109）
3. `TransportBulkAction`が各操作をインデックスごとにグループ化し、インジェストパイプラインの適用が必要な場合はIngestServiceを呼び出す
4. シャードごとに`BulkShardRequest`を構築し、各シャードに対して並列実行する
5. 全シャードの結果を集約し、`BulkResponse`を構築して返却する

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| index操作 | Luceneインデックス | INSERT/UPDATE | ドキュメントの登録または更新 |
| create操作 | Luceneインデックス | INSERT | 新規ドキュメントの作成（既存時エラー） |
| update操作 | Luceneインデックス | UPDATE | 既存ドキュメントの部分更新 |
| delete操作 | Luceneインデックス | DELETE | ドキュメントの削除 |

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

#### Luceneインデックス

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| INSERT (index/create) | _source | リクエストボディのドキュメントデータ | インジェストパイプライン適用後の値 |
| INSERT (index/create) | _version | 自動インクリメント | 楽観的排他制御に使用 |
| UPDATE | _source | スクリプトまたは部分ドキュメントによる更新 | update操作時 |
| DELETE | - | _idで指定されたドキュメント | 論理削除マーカー |

## メッセージ仕様

| メッセージ種別 | 条件 | メッセージ内容 |
|--------------|------|--------------|
| 成功 | 全操作成功 | HTTPステータス200、errors=false |
| 部分成功 | 一部操作失敗 | HTTPステータス200、errors=true、各itemsにstatus/errorが含まれる |
| エラー | リクエストボディ形式不正 | HTTPステータス400、パースエラー |
| エラー | タイムアウト | 各操作のerrorにtimeoutエラーが含まれる |

## 例外処理

| 例外 | 条件 | 動作 |
|------|------|------|
| BulkRequestParseException | NDJSON形式の解析エラー | リクエスト全体が失敗 |
| VersionConflictEngineException | バージョンコンフリクト | 該当操作のみ失敗、他は正常処理 |
| MapperParsingException | マッピング解析エラー | 該当操作のみ失敗 |
| IndexNotFoundException | 対象インデックスが存在しない場合 | 該当操作のみ失敗（auto_create_index設定に依存） |

## 備考

- リクエストボディはNDJSON形式であり、Content-Typeは`application/x-ndjson`を推奨
- `supportsContentStream()`がtrueを返すため、ストリーミング解析に対応（行115-117）
- `allowsUnsafeBuffers()`がtrueを返すため、パフォーマンス最適化のためにアンセーフバッファを使用（行119-122）
- 各操作は独立して成功・失敗するため、1つの操作の失敗が他の操作に影響しない
- `require_alias`パラメータにより、エイリアスを介した書き込みを強制できる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | bulk.json | `rest-api-spec/src/main/resources/rest-api-spec/api/bulk.json` | APIのURL、メソッド、パラメータ定義。bodyのserialize="bulk"に注目 |
| 1-2 | BulkRequest.java | `server/src/main/java/org/opensearch/action/bulk/BulkRequest.java` | リクエストのデータ構造。add()メソッドのNDJSON解析ロジック |
| 1-3 | BulkResponse.java | `server/src/main/java/org/opensearch/action/bulk/BulkResponse.java` | レスポンス構造。items配列とerrorsフラグ |

**読解のコツ**: BulkRequest.add()内のNDJSON解析ロジックが本APIの核心。アクション行のパースと、操作種別ごとのDocWriteRequest生成フローを追う。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestBulkAction.java | `server/src/main/java/org/opensearch/rest/action/document/RestBulkAction.java` | RESTハンドラの実装 |

**主要処理フロー**:
1. **行75-78**: routes()でPOST/PUTの`/_bulk`と`/{index}/_bulk`の4ルートを定義
2. **行87-112**: prepareRequest()でパラメータ解析、BulkRequestの構築
3. **行88-99**: デフォルトインデックス、ルーティング、パイプライン等の設定
4. **行100-109**: NDJSONボディの解析とリクエストへの追加
5. **行111**: NodeClient.bulk()の呼び出し

#### Step 3: Transport層のバルク処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TransportBulkAction.java | `server/src/main/java/org/opensearch/action/bulk/TransportBulkAction.java` | バルク操作の実行・分散・集約ロジック |

**主要処理フロー**:
- インジェストパイプライン適用の判定と実行
- インデックスの自動作成処理
- シャードごとのリクエスト分散
- 全シャードの結果集約

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

```
RestBulkAction.prepareRequest()                     [行87]
    |
    +-- BulkRequest.add()                           [NDJSONパース]
    |       +-- IndexRequest / DeleteRequest / UpdateRequest 生成
    |
    +-- NodeClient.bulk()
            |
            +-- TransportBulkAction.doExecute()
                    |
                    +-- IngestService.executeBulkRequest()  [パイプライン適用時]
                    |
                    +-- AutoCreateIndex.shouldAutoCreate()  [インデックス自動作成]
                    |
                    +-- BulkShardRequest (各シャードへ分散)
                            |
                            +-- TransportShardBulkAction.execute()
```

### データフロー図

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

HTTPリクエスト                RestBulkAction                      BulkResponse
(POST /_bulk)            パラメータ解析・リクエスト構築
   |                              |
   v                              v
NDJSONボディ               TransportBulkAction                  レスポンスJSON
{action}\n{data}\n     操作分散・パイプライン適用               {took, errors, items}
   |                              |
   v                              v
各操作ペア              TransportShardBulkAction                各操作の結果
(index/create/          シャード内操作実行                     (status/error)
 update/delete)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| bulk.json | `rest-api-spec/src/main/resources/rest-api-spec/api/bulk.json` | API定義 | REST API仕様の定義 |
| RestBulkAction.java | `server/src/main/java/org/opensearch/rest/action/document/RestBulkAction.java` | ソース | RESTハンドラ |
| TransportBulkAction.java | `server/src/main/java/org/opensearch/action/bulk/TransportBulkAction.java` | ソース | Transport層のバルク実行処理 |
| BulkRequest.java | `server/src/main/java/org/opensearch/action/bulk/BulkRequest.java` | ソース | リクエストデータ構造・NDJSONパース |
| BulkResponse.java | `server/src/main/java/org/opensearch/action/bulk/BulkResponse.java` | ソース | レスポンスデータ構造 |
| BulkShardRequest.java | `server/src/main/java/org/opensearch/action/bulk/BulkShardRequest.java` | ソース | シャード別バルクリクエスト |
| TransportShardBulkAction.java | `server/src/main/java/org/opensearch/action/bulk/TransportShardBulkAction.java` | ソース | シャードレベルのバルク実行 |
