# 画面設計書 51-マッピング更新

## 概要

本ドキュメントは、OpenSearchのPut Mapping API（`PUT/POST /{index}/_mapping`）に関する画面設計書である。インデックスのマッピング定義を更新するためのREST APIエンドポイントの仕様を定義する。

### 本画面の処理概要

本APIは、既存インデックスに対してフィールドマッピングの追加・変更を行うためのエンドポイントである。

**業務上の目的・背景**：インデックスに格納するドキュメントの構造（フィールド名、データ型、アナライザ設定等）を定義・更新する必要がある。新しいフィールドの追加や、既存フィールドのパラメータ変更（ただし、型変更など破壊的変更は不可）を行う際に使用する。マッピングはドキュメントの検索・集計のパフォーマンスおよび精度に直接影響するため、適切なマッピング管理は運用上不可欠である。

**画面へのアクセス方法**：REST APIクライアント（curl、OpenSearch Dashboards Dev Tools等）から `PUT /{index}/_mapping` または `POST /{index}/_mapping` エンドポイントにリクエストを送信する。

**主要な操作・処理内容**：
1. リクエストボディに含まれるマッピング定義を解析し、対象インデックスのマッピングを更新する
2. ワイルドカードやカンマ区切りで複数インデックスを一括指定可能
3. `write_index_only` オプションにより、エイリアスやデータストリームの書き込みインデックスのみに適用可能
4. クラスタマネージャノードへの通信タイムアウトや操作タイムアウトを制御可能

**画面遷移**：本APIは単独で完結するが、典型的にはインデックス作成（No.38）後にマッピングを追加・変更する場合や、マッピング取得（No.50）で現在のマッピングを確認した後に呼び出される。更新後はマッピング取得（No.50）やフィールドマッピング取得（No.52）で結果を確認する。

**権限による表示制御**：Security Pluginが有効な場合、対象インデックスへの `indices:admin/mapping/put` アクション権限が必要である。権限不足の場合は403エラーが返却される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | マッピング管理 | 主機能 | インデックスマッピングを更新する処理 |

## 画面種別

API実行（更新系）

## URL/ルーティング

| メソッド | パス | 説明 |
|---------|------|------|
| PUT | `/{index}/_mapping` | インデックスのマッピングを更新 |
| POST | `/{index}/_mapping` | インデックスのマッピングを更新 |
| PUT | `/{index}/_mappings` | インデックスのマッピングを更新（複数形パス） |
| POST | `/{index}/_mappings` | インデックスのマッピングを更新（複数形パス） |

## 入出力項目

### パスパラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|------|------|------|
| index | list(string) | Yes | 対象インデックス名（カンマ区切りリスト、ワイルドカード対応、`_all`で全インデックス） |

### クエリパラメータ

| パラメータ名 | 型 | 必須 | デフォルト | 説明 |
|-------------|------|------|-----------|------|
| timeout | time | No | 30s | 操作タイムアウト |
| cluster_manager_timeout | time | No | 30s | クラスタマネージャノードへの接続タイムアウト |
| master_timeout | time | No | 30s | クラスタマネージャノードへの接続タイムアウト（非推奨、cluster_manager_timeoutを使用） |
| ignore_unavailable | boolean | No | false | 利用不可なインデックスを無視するか |
| allow_no_indices | boolean | No | false | ワイルドカードが何にもマッチしない場合にエラーにしないか |
| expand_wildcards | enum | No | open | ワイルドカード展開対象（open/closed/hidden/none/all） |
| write_index_only | boolean | No | false | エイリアス・データストリームの書き込みインデックスのみに適用するか |

### リクエストボディ

| 項目 | 型 | 必須 | 説明 |
|------|------|------|------|
| properties | object | Yes | フィールドマッピング定義（フィールド名をキー、マッピング設定をバリュー） |

## 表示項目

### レスポンスボディ

| 項目 | 型 | 説明 |
|------|------|------|
| acknowledged | boolean | リクエストが受理されたか |

## イベント仕様

### 1-マッピング更新リクエスト

1. クライアントがPUT/POSTリクエストを送信
2. `RestPutMappingAction.prepareRequest()` がリクエストを解析し、`PutMappingRequest` オブジェクトを生成
3. リクエストボディのマッピング定義を `XContentHelper.convertToMap()` でMap形式に変換
4. 型付きマッピング（types）の指定がある場合は `IllegalArgumentException` をスロー
5. `TransportPutMappingAction` がクラスタマネージャノードにリクエストを転送
6. `MetadataMappingService` がマッピングの検証と更新を実行
7. クラスタ状態が更新され、成功レスポンスを返却

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| マッピング更新リクエスト | クラスタメタデータ（IndexMetadata） | UPDATE | インデックスのマッピング定義をクラスタ状態内で更新 |

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

#### クラスタメタデータ（IndexMetadata.mapping）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | MappingMetadata | リクエストボディで指定されたマッピング定義をマージ | 既存フィールドとの互換性チェックあり |

## メッセージ仕様

| メッセージ種別 | HTTPステータス | メッセージ内容 | 発生条件 |
|-------------|--------------|--------------|---------|
| 成功 | 200 | `{"acknowledged": true}` | マッピング更新が正常に完了 |
| エラー | 400 | `Types cannot be provided in put mapping requests` | 型付きマッピングを指定した場合 |
| エラー | 400 | `mapper [field] cannot be changed from type [x] to [y]` | 既存フィールドの型を変更しようとした場合 |
| エラー | 404 | `no such index [index_name]` | 指定インデックスが存在しない場合 |
| エラー | 403 | アクセス拒否 | 権限不足の場合 |

## 例外処理

| 例外 | 条件 | 動作 |
|------|------|------|
| IndexNotFoundException | 指定したインデックスが存在しない | 404エラーを返却 |
| IllegalArgumentException | 型付きマッピング指定、不正なマッピング定義 | 400エラーを返却 |
| MapperParsingException | マッピング定義のパースに失敗 | 400エラーを返却 |
| ClusterManagerNotDiscoveredException | クラスタマネージャノードに接続不可 | 503エラーを返却 |
| ProcessClusterEventTimeoutException | タイムアウト | 408/500エラーを返却 |

## 備考

- マッピングの更新は追加的（additive）な変更のみ許可される。既存フィールドの型変更は不可。
- `_all` インデックスの利用は非推奨。
- `master_timeout` パラメータはバージョン2.0.0で非推奨となり、`cluster_manager_timeout` に置き換えられた。

---

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

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

### 推奨読解順序

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

まず、マッピング更新リクエストで受け渡されるデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | PutMappingRequest.java | `server/src/main/java/org/opensearch/action/admin/indices/mapping/put/PutMappingRequest.java` | マッピング更新リクエストのデータモデル。indices、source、timeout等のフィールドを確認 |
| 1-2 | indices.put_mapping.json | `rest-api-spec/src/main/resources/rest-api-spec/api/indices.put_mapping.json` | REST APIの仕様定義。パス、パラメータ、ボディの定義を確認 |

**読解のコツ**: `PutMappingRequest` はクラスタマネージャノードに転送されるため `ClusterManagerNodeRequest` を継承している。`source` フィールドにマッピング定義のJSON文字列が格納される。

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

RESTリクエストの受信とパラメータ解析の起点。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestPutMappingAction.java | `server/src/main/java/org/opensearch/rest/action/admin/indices/RestPutMappingAction.java` | RESTリクエストのルーティングとパラメータ解析 |

**主要処理フロー**:
1. **行69-73**: ルーティング定義（PUT/POST `/{index}/_mapping` および `/{index}/_mappings`）
2. **行85**: インデックス名をカンマ区切りで分割し `PutMappingRequest` を生成
3. **行86**: リクエストボディをMap形式に変換
4. **行88-90**: 型付きマッピングのチェック（禁止）
5. **行92-99**: タイムアウト、IndicesOptions、writeIndexOnlyのパラメータ設定
6. **行100**: クライアント経由でトランスポートアクションを呼び出し

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

クラスタマネージャノードでのマッピング更新処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TransportPutMappingAction.java | `server/src/main/java/org/opensearch/action/admin/indices/mapping/put/TransportPutMappingAction.java` | クラスタマネージャノードでのマッピング更新処理の実行 |

**主要処理フロー**:
- クラスタマネージャノードで実行され、`MetadataMappingService.putMapping()` を呼び出してクラスタ状態を更新する

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

```
RestPutMappingAction.prepareRequest() [行83-101]
    │
    ├─ XContentHelper.convertToMap() [行86] - リクエストボディの解析
    │
    ├─ MapperService.isMappingSourceTyped() [行88] - 型付きマッピングチェック
    │
    └─ NodeClient.admin().indices().putMapping() [行100]
           │
           └─ TransportPutMappingAction.masterOperation()
                  │
                  └─ MetadataMappingService.putMapping()
                         │
                         └─ MapperService.merge() - マッピングのマージと検証
```

### データフロー図

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

PUT /{index}/_mapping   ───▶ RestPutMappingAction              ───▶ {"acknowledged": true}
  + Request Body               │
  (マッピング定義JSON)          ├─ パラメータ解析
                               ├─ PutMappingRequest生成
                               └─ TransportPutMappingAction
                                     │
                                     └─ MetadataMappingService
                                           │
                                           └─ クラスタ状態更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RestPutMappingAction.java | `server/src/main/java/org/opensearch/rest/action/admin/indices/RestPutMappingAction.java` | ソース | RESTエンドポイントハンドラ |
| TransportPutMappingAction.java | `server/src/main/java/org/opensearch/action/admin/indices/mapping/put/TransportPutMappingAction.java` | ソース | トランスポートアクション |
| PutMappingRequest.java | `server/src/main/java/org/opensearch/action/admin/indices/mapping/put/PutMappingRequest.java` | ソース | リクエストモデル |
| MetadataMappingService.java | `server/src/main/java/org/opensearch/cluster/metadata/MetadataMappingService.java` | ソース | マッピング更新サービス |
| MapperService.java | `server/src/main/java/org/opensearch/index/mapper/MapperService.java` | ソース | マッパーサービス（マッピングの検証・マージ） |
| indices.put_mapping.json | `rest-api-spec/src/main/resources/rest-api-spec/api/indices.put_mapping.json` | 設定 | REST API仕様定義 |
