# 画面設計書 17-Reindex

## 概要

本ドキュメントは、OpenSearchのReindex API（`_reindex`）エンドポイントに関する画面設計書である。あるインデックスから別のインデックスにドキュメントをコピーするためのREST APIインターフェースを定義する。

### 本画面の処理概要

本APIは、ソースインデックスからドキュメントを読み取り、宛先インデックスに書き込む機能を提供する。オプションでクエリフィルタリング、ソースフィルタリング、スクリプトによる変換、リモートクラスタからのReindexにも対応する。

**業務上の目的・背景**：インデックスのマッピング変更（フィールド型の変更など）は既存データに遡及適用できないため、新しいマッピングを持つインデックスにデータを移行する必要がある。また、インデックスの統合・分割、シャード数の変更、別クラスタへのデータ移行などのユースケースにおいて、Reindex APIは不可欠な機能である。リモートクラスタからのReindexもサポートしており、クラスタ間のデータ移行にも使用できる。

**画面へのアクセス方法**：HTTPクライアントから`POST /_reindex`エンドポイントにソース・宛先インデックスの指定を含むリクエストボディを送信する。

**主要な操作・処理内容**：
1. リクエストボディからソースインデックス、宛先インデックス、クエリ条件、スクリプト等を解析する
2. ソースインデックスからスクロール検索でドキュメントを段階的に取得する
3. 必要に応じてスクリプトで変換を適用する
4. 宛先インデックスにバルク操作でドキュメントを書き込む
5. リモートクラスタからのReindexの場合、リモートクラスタへの接続を確立して読み取る

**画面遷移**：Reindexスロットル変更（No.18）と連携して実行中タスクのスロットルを変更できる。タスク取得（No.113）やタスクキャンセル（No.114）との連携で非同期タスクの管理が可能。

**権限による表示制御**：ソースインデックスに対するread権限、宛先インデックスに対するindex権限が必要。リモートReindexの場合はリモートクラスタへの接続権限も必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | リインデックス | 主機能 | あるインデックスから別のインデックスにドキュメントをコピーする主処理 |
| 19 | 全文検索 | 補助機能 | ソースインデックスからドキュメントを取得するための検索処理 |

## 画面種別

API（インデックス間ドキュメントコピー）

## URL/ルーティング

| メソッド | パス | 説明 |
|---------|------|------|
| POST | `/_reindex` | ソースから宛先へドキュメントをコピー |

## 入出力項目

### クエリパラメータ

| パラメータ | 型 | 必須 | デフォルト | 説明 |
|-----------|------|------|-----------|------|
| refresh | boolean | いいえ | - | 影響インデックスのリフレッシュ |
| timeout | time | いいえ | 1m | 各バルクリクエストのタイムアウト |
| wait_for_active_shards | string | いいえ | 1 | アクティブシャードコピー数の要件 |
| wait_for_completion | boolean | いいえ | true | 完了までブロックするかどうか |
| requests_per_second | number | いいえ | 0 (無制限) | スロットル値（-1でスロットルなし） |
| scroll | time | いいえ | 5m | スクロール検索のコンテキスト維持時間 |
| slices | number/string | いいえ | 1 | タスク分割スライス数 |
| max_docs | number | いいえ | 全件 | 処理する最大ドキュメント数 |

### リクエストボディ

| フィールド | 型 | 必須 | 説明 |
|-----------|------|------|------|
| source | object | はい | ソースインデックスの指定 |
| source.index | string/array | はい | ソースインデックス名 |
| source.query | object | いいえ | 対象ドキュメントのフィルタクエリ |
| source._source | array | いいえ | コピーするフィールドのリスト |
| source.remote | object | いいえ | リモートクラスタ接続情報 |
| source.remote.host | string | はい（remote使用時） | リモートクラスタのホストURL |
| source.remote.username | string | いいえ | リモートクラスタの認証ユーザー名 |
| source.remote.password | string | いいえ | リモートクラスタの認証パスワード |
| source.size | number | いいえ | スクロール検索のバッチサイズ |
| dest | object | はい | 宛先インデックスの指定 |
| dest.index | string | はい | 宛先インデックス名 |
| dest.pipeline | string | いいえ | 適用するインジェストパイプラインID |
| dest.routing | string | いいえ | ルーティング設定（keep/discard/=value） |
| dest.version_type | string | いいえ | バージョン管理方法 |
| dest.op_type | string | いいえ | 操作タイプ（index/create） |
| script | object | いいえ | 変換スクリプト |
| conflicts | string | いいえ | コンフリクト時の動作（proceed/abort） |
| max_docs | number | いいえ | 処理する最大ドキュメント数 |

## 表示項目

### レスポンスボディ

| フィールド | 型 | 説明 |
|-----------|------|------|
| took | number | 処理にかかった時間（ミリ秒） |
| timed_out | boolean | タイムアウトしたかどうか |
| total | number | 処理されたドキュメントの総数 |
| created | number | 作成されたドキュメント数 |
| updated | number | 更新されたドキュメント数 |
| deleted | number | 削除されたドキュメント数 |
| batches | number | バッチ数 |
| version_conflicts | number | バージョンコンフリクト数 |
| noops | number | 操作なしの数 |
| retries | object | リトライ回数 |
| throttled_millis | number | スロットリング待機時間 |
| failures | array | 失敗情報の配列 |

## イベント仕様

### 1-Reindexリクエスト実行

1. `RestReindexAction.prepareRequest()`が`doPrepareRequest(request, client, true, true)`を呼び出す（行71-73）。第3引数`true`はリクエストボディの必須を示す。
2. `buildRequest()`でReindexRequestを構築する（行76-96）
3. `pipeline`クエリパラメータが指定されている場合、IllegalArgumentExceptionをスロー（行77-80）。パイプラインはdestオブジェクト内で指定する必要がある。
4. `ReindexRequest.fromXContent(parser)`でリクエストボディをパースする（行84-86）
5. `scroll`パラメータが指定されている場合、スクロール時間を設定する（行88-90）
6. `require_alias`パラメータが指定されている場合、設定する（行91-93）
7. リモートReindexの場合、`source.remote.host.password`フィールドはフィルタリングされる（行98-103）

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Reindexリクエスト | ソースLuceneインデックス | SELECT | ソースインデックスからドキュメントをスクロール検索 |
| Reindexリクエスト | 宛先Luceneインデックス | INSERT/UPDATE | 宛先インデックスにドキュメントを書き込む |

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

#### 宛先Luceneインデックス

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| INSERT/UPDATE | _source | ソースドキュメント（スクリプト適用後） | op_type=createの場合はINSERTのみ |
| INSERT/UPDATE | _version | ソースバージョンまたは新規バージョン | version_type設定に依存 |

## メッセージ仕様

| メッセージ種別 | 条件 | メッセージ内容 |
|--------------|------|--------------|
| 成功 | 全件コピー成功 | HTTPステータス200、failures配列が空 |
| エラー | pipelineクエリパラメータ使用 | "_reindex doesn't support [pipeline] as a query parameter. Specify it in the [dest] object instead." |
| エラー | コンフリクト（conflicts=abort） | バージョンコンフリクトエラー |
| 非同期 | wait_for_completion=false | HTTPステータス200、タスクIDを含むレスポンス |

## 例外処理

| 例外 | 条件 | 動作 |
|------|------|------|
| IllegalArgumentException | pipelineをクエリパラメータとして指定 | リクエスト全体が失敗 |
| VersionConflictEngineException | conflicts=abortでバージョンコンフリクト | 処理中断 |
| ConnectTransportException | リモートクラスタ接続失敗 | リクエスト全体が失敗 |

## 備考

- `pipeline`パラメータはクエリパラメータではなく、リクエストボディの`dest.pipeline`で指定する必要がある（行77-80）
- リモートReindexでは、パスワードがログに記録されないよう`FILTERED_FIELDS`でフィルタリングされる（行98-103）
- `RestRequestFilter`インターフェースを実装しており、セキュリティ対策が組み込まれている（行54）
- `scroll`のデフォルト値は5m（5分）であり、Delete By Query/Update By Queryとは異なる
- `require_alias`パラメータにより、エイリアス経由の書き込みを強制できる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | reindex.json | `rest-api-spec/src/main/resources/rest-api-spec/api/reindex.json` | API定義。パラメータがDelete By Query/Update By Queryより少ないことに注目 |
| 1-2 | ReindexRequest.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/ReindexRequest.java` | リクエストデータ構造。fromXContent()によるボディパースが特徴的 |

**読解のコツ**: ReindexRequestはAbstractBulkByScrollRequestを継承しているが、Delete By Query/Update By Queryとは異なり、リクエストボディのパースにfromXContent()メソッドを使用する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestReindexAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/RestReindexAction.java` | RESTハンドラ。RestRequestFilterの実装にも注目 |

**主要処理フロー**:
1. **行62**: routes()でPOST /_reindexのルートを定義
2. **行71-73**: prepareRequest()でdoPrepareRequest(request, client, true, true)を呼び出し
3. **行76-96**: buildRequest()でReindexRequestを構築
4. **行77-80**: pipelineクエリパラメータの禁止チェック
5. **行84-86**: ReindexRequest.fromXContent()によるボディパース
6. **行88-93**: scroll, require_aliasパラメータの設定
7. **行98-103**: FILTERED_FIELDSによるパスワードフィルタリング

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

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

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

```
RestReindexAction.prepareRequest()                      [行71]
    |
    +-- doPrepareRequest(request, client, true, true)
            |
            +-- buildRequest()                          [行76]
            |       +-- ReindexRequest.fromXContent()   [行84-86]
            |       +-- setScroll()                     [行88-90]
            |       +-- setRequireAlias()               [行91-93]
            |
            +-- NodeClient.execute(ReindexAction.INSTANCE, ...)
                    |
                    +-- TransportReindexAction
                            +-- スクロール検索(source) → バルク書込(dest)
```

### データフロー図

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

HTTPリクエスト              RestReindexAction                    BulkByScrollResponse
(POST /_reindex)        リクエスト解析・構築
   |                            |
   v                            v
リクエストボディ         TransportReindexAction                  レスポンスJSON
{source:{...},         ソース読取→宛先書込                      {took, created,
 dest:{...},                    |                                updated,...}
 script:{...}}                  v
                        [リモートReindex時]
                        RemoteScrollableHitSource
                        リモートクラスタからのスクロール読取
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| reindex.json | `rest-api-spec/src/main/resources/rest-api-spec/api/reindex.json` | API定義 | REST API仕様 |
| RestReindexAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/RestReindexAction.java` | ソース | RESTハンドラ |
| ReindexRequest.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/ReindexRequest.java` | ソース | リクエストデータ構造 |
| AbstractBaseReindexRestHandler.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/AbstractBaseReindexRestHandler.java` | ソース | 共通実行処理 |
| TransportReindexAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/TransportReindexAction.java` | ソース | Transport層の実行処理 |
| BulkByScrollResponse.java | `server/src/main/java/org/opensearch/index/reindex/BulkByScrollResponse.java` | ソース | レスポンスデータ構造 |
| RemoteScrollableHitSource.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/remote/RemoteScrollableHitSource.java` | ソース | リモートReindex時のスクロール読取 |
