# 画面設計書 6-ドキュメントソース取得

## 概要

OpenSearchインデックスからドキュメントのソース（_source）のみを取得するREST APIエンドポイント（GET /{index}/_source/{id}）の設計書である。メタデータを含まず、ドキュメントの本体データのみを直接返却する。

### 本画面の処理概要

本APIは、ドキュメントIDを指定してインデックスからドキュメントのソースデータのみを取得する機能を提供する。

**業務上の目的・背景**：ドキュメント取得API（GET /{index}/_doc/{id}）はメタデータ（_index, _id, _version等）を含む完全なレスポンスを返すが、アプリケーションによってはドキュメントの本体データのみが必要な場合がある。本APIはメタデータを省略し、_sourceフィールドの内容を直接返却することで、レスポンスサイズの削減とパース処理の簡略化を実現する。

**画面へのアクセス方法**：HTTPクライアントからGETメソッドで `/{index}/_source/{id}` にリクエストを送信する。

**主要な操作・処理内容**：
1. クライアントからGETリクエストを受信する
2. インデックス名、ドキュメントIDを解析する
3. GetRequestを構築し、ドキュメントを取得する
4. ドキュメントのソースデータのみをJSON形式で返却する
5. ドキュメントが存在しない場合、またはソースが空の場合はResourceNotFoundExceptionをスローする

**画面遷移**：ドキュメント登録・更新API（PUT/POST /{index}/_doc/{id}）で登録されたドキュメントのソースを本APIで取得できる。

**権限による表示制御**：インデックスへの読み取り権限が必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 11 | ドキュメント取得 | 主機能 | ドキュメントのソース（_source）のみを返す処理 |

## 画面種別

詳細（参照系API）

## URL/ルーティング

| メソッド | パス | 説明 |
|---------|------|------|
| GET | `/{index}/_source/{id}` | ドキュメントのソースを取得する |

## 入出力項目

### パスパラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| index | string | はい | インデックス名 |
| id | string | はい | ドキュメントID |

### クエリパラメータ

| パラメータ名 | 型 | 必須 | デフォルト | 説明 |
|-------------|-----|------|----------|------|
| preference | string | いいえ | random | 操作を実行するノードまたはシャードの指定 |
| realtime | boolean | いいえ | true | リアルタイムモードで取得するか |
| refresh | boolean | いいえ | false | 取得前にシャードをリフレッシュする |
| routing | string | いいえ | - | ルーティング値 |
| _source | list | いいえ | true | _sourceフィールドの返却制御（falseは不可） |
| _source_excludes | list | いいえ | - | _sourceから除外するフィールドリスト |
| _source_includes | list | いいえ | - | _sourceから抽出するフィールドリスト |
| version | number | いいえ | - | 楽観的排他制御用バージョン番号 |
| version_type | enum (internal, external, external_gte, force) | いいえ | internal | バージョンタイプ |

### レスポンスボディ

レスポンスはドキュメントのソースデータそのものである。メタデータは含まない。

```json
{
  "field1": "value1",
  "field2": "value2"
}
```

## 表示項目

ドキュメントの_sourceフィールドの内容がそのまま表示される。_source_includes/_source_excludesによるフィルタリングが適用される。

## イベント仕様

### 1-ドキュメントソース取得

1. GET `/{index}/_source/{id}` リクエストを受信する
2. `RestGetSourceAction.prepareRequest()` がリクエストパラメータを解析する（79-97行目）
3. `GetRequest` オブジェクトを構築する
4. `FetchSourceContext.parseFromRestRequest()` でソースフィルタリングを設定する（86行目）
5. fetchSourceがfalseに設定されていないことを検証する（89-92行目）
6. `client.get()` でドキュメント取得を実行する（94行目）
7. `RestGetSourceResponseListener.buildResponse()` でレスポンスを構築する（108-116行目）
8. ドキュメント未存在またはソース空の場合は `ResourceNotFoundException` をスローする（125-133行目）

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| GET /{index}/_source/{id} | 指定インデックス | SELECT | ドキュメントソースを取得する（更新なし） |

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

本APIはデータベース（インデックス）の更新を行わない。読み取り専用の操作である。

## メッセージ仕様

| メッセージ種別 | HTTPステータス | 条件 | メッセージ内容 |
|--------------|--------------|------|-------------|
| 成功 | 200 OK | ドキュメントが見つかりソースが存在する場合 | ドキュメントソースのJSON |
| ドキュメント未存在 | 404 Not Found | ドキュメントが見つからない場合 | "Document not found [{index}]/[{id}]" |
| ソース未存在 | 404 Not Found | ドキュメントは存在するがソースが空の場合 | "Source not found [{index}]/[{id}]" |
| バリデーションエラー | 400 Bad Request | _source=falseが指定された場合 | "fetching source can not be disabled" |

## 例外処理

| 例外 | HTTPステータス | 条件 | レスポンス |
|------|--------------|------|----------|
| ResourceNotFoundException | 404 | ドキュメントが存在しない場合 | Document not found メッセージ |
| ResourceNotFoundException | 404 | ドキュメントのソースが空の場合 | Source not found メッセージ |
| ActionRequestValidationException | 400 | fetchSourceがfalseの場合 | "fetching source can not be disabled" |

## 備考

- 本APIはドキュメント取得API（GET /{index}/_doc/{id}）と内部的にGetRequestを共有するが、レスポンスの構築ロジックが異なる。RestGetSourceResponseListenerがソースデータのみをレスポンスとして返却する。
- HEAD /{index}/_source/{id}（ドキュメントソース存在確認API）もRestGetSourceActionで処理される（70行目でHEADルートが登録）。
- _source=falseを指定するとバリデーションエラーとなる。ソース取得APIでソースの取得を無効化することは論理的に矛盾するため。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | GetRequest.java | `server/src/main/java/org/opensearch/action/get/GetRequest.java` | ドキュメント取得APIと共通のリクエスト構造 |
| 1-2 | GetResponse.java | `server/src/main/java/org/opensearch/action/get/GetResponse.java` | isExists()、isSourceEmpty()、getSourceInternal()メソッドの理解 |

**読解のコツ**: GetResponseの `getSourceInternal()` がソースデータのBytesReferenceを返す。isSourceEmpty()でソースの存在チェックを行う。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestGetSourceAction.java | `server/src/main/java/org/opensearch/rest/action/document/RestGetSourceAction.java` | ルーティング（70行目）、パラメータ解析（79-97行目）、レスポンスリスナー（99-135行目）を確認する |

**主要処理フロー**:
1. **70行目**: GETとHEAD両方のルーティングを `/{index}/_source/{id}` で登録
2. **80行目**: GetRequestをindex, idで初期化
3. **81-84行目**: refresh, routing, preference, realtimeの設定
4. **86行目**: FetchSourceContextの設定
5. **89-92行目**: fetchSource=falseのバリデーション
6. **94行目**: client.get()の実行
7. **108-116行目**: buildResponse()でソースデータのみをレスポンスとして返却
8. **125-133行目**: checkResource()でドキュメント/ソースの存在チェック

#### Step 3: レスポンス構築を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | RestGetSourceResponseListener | 同上ファイル内 (99-135行目) | ソースデータの抽出とResourceNotFoundExceptionの条件を確認する |

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

```
RestGetSourceAction.prepareRequest()
    |
    +-- GetRequest 構築
    +-- FetchSourceContext 設定
    +-- fetchSource=false チェック
    |
    +-- client.get(getRequest, RestGetSourceResponseListener)
            |
            +-- TransportGetAction
                    |
                    +-- ShardGetService.get()
                            |
                            +-- RestGetSourceResponseListener.buildResponse()
                                    |
                                    +-- checkResource() [存在チェック]
                                    |   +-- ResourceNotFoundException (未存在時)
                                    |
                                    +-- response.getSourceInternal()
                                    +-- builder.rawValue(source)
                                    +-- BytesRestResponse(OK, builder)
```

### データフロー図

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

GET /{index}/_source/{id}  --> RestGetSourceAction          --> HTTP 200
                                 |                              { "field1": "value1", ... }
                                 v                              (ソースのみ)
                           GetRequest構築
                                 |
                                 v
                           TransportGetAction
                                 |
                                 v                          --> HTTP 404
                           GetResponse                          ResourceNotFoundException
                                 |                              (ドキュメントまたは
                                 v                               ソース未存在)
                           checkResource()
                           getSourceInternal()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RestGetSourceAction.java | `server/src/main/java/org/opensearch/rest/action/document/RestGetSourceAction.java` | ソース | RESTハンドラ（エントリーポイント） |
| GetRequest.java | `server/src/main/java/org/opensearch/action/get/GetRequest.java` | ソース | リクエストオブジェクト |
| GetResponse.java | `server/src/main/java/org/opensearch/action/get/GetResponse.java` | ソース | レスポンスオブジェクト |
| TransportGetAction.java | `server/src/main/java/org/opensearch/action/get/TransportGetAction.java` | ソース | トランスポートアクション |
| FetchSourceContext.java | `server/src/main/java/org/opensearch/search/fetch/subphase/FetchSourceContext.java` | ソース | ソースフィルタリング |
| get_source.json | `rest-api-spec/src/main/resources/rest-api-spec/api/get_source.json` | 設定 | REST API仕様定義 |
| RestGetSourceActionTests.java | `server/src/test/java/org/opensearch/rest/action/document/RestGetSourceActionTests.java` | テスト | ユニットテスト |
