# 画面設計書 8-ドキュメントソース存在確認

## 概要

OpenSearchインデックスにドキュメントソースが存在するかを確認するREST APIエンドポイント（HEAD /{index}/_source/{id}）の設計書である。レスポンスボディを返さず、HTTPステータスコード（200または404）でドキュメントソースの存在有無を判定する。

### 本画面の処理概要

本APIは、ドキュメントIDを指定してインデックスにドキュメントソース（_source）が存在するかどうかを確認する機能を提供する。

**業務上の目的・背景**：ドキュメントが存在していても、マッピングで_sourceが無効化されている場合はソースデータが取得できない。本APIはソースの取得可否を事前に確認するために使用する。また、ドキュメントの存在確認としても機能する（ドキュメント自体が存在しなければ当然ソースも存在しない）。ソース取得API呼び出し前の事前チェックとして有用である。

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

**主要な操作・処理内容**：
1. クライアントからHEADリクエストを受信する
2. インデックス名、ドキュメントIDを解析する
3. ドキュメントの存在とソースの存在をチェックする
4. ソースが存在する場合はHTTP 200、存在しない場合はHTTP 404を返す（ボディなし）

**画面遷移**：本APIでドキュメントソースの存在を確認した後、ドキュメントソース取得API（GET /{index}/_source/{id}）でソースを取得する操作が想定される。

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 11 | ドキュメント取得 | 主機能 | ドキュメントソースが存在するかを確認する処理 |

## 画面種別

存在確認（参照系API）

## URL/ルーティング

| メソッド | パス | 説明 |
|---------|------|------|
| HEAD | `/{index}/_source/{id}` | ドキュメントソースの存在を確認する |

## 入出力項目

### パスパラメータ

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

### クエリパラメータ

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

### レスポンス

レスポンスボディは返却されない。HTTPステータスコードのみで結果を伝える。

| HTTPステータス | 意味 |
|--------------|------|
| 200 OK | ドキュメントソースが存在する |
| 404 Not Found | ドキュメントまたはソースが存在しない |

## 表示項目

レスポンスボディなし。HTTPヘッダのみが返却される。

## イベント仕様

### 1-ドキュメントソース存在確認

1. HEAD `/{index}/_source/{id}` リクエストを受信する
2. `RestGetSourceAction.prepareRequest()` がリクエストパラメータを解析する（ドキュメントソース取得APIと同じハンドラ）
3. `GetRequest` オブジェクトを構築する
4. fetchSourceがfalseに設定されていないことを検証する
5. `client.get()` でドキュメント取得を実行する
6. `RestGetSourceResponseListener.buildResponse()` でレスポンスを構築する
7. `checkResource()` でドキュメントとソースの存在をチェックする
8. 存在する場合はHTTP 200、未存在の場合はResourceNotFoundExceptionが404に変換される（HEADのためボディは破棄）

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

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

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

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

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

## メッセージ仕様

| メッセージ種別 | HTTPステータス | 条件 | メッセージ内容 |
|--------------|--------------|------|-------------|
| 存在 | 200 OK | ドキュメントソースが存在する場合 | ボディなし |
| 未存在 | 404 Not Found | ドキュメントまたはソースが存在しない場合 | ボディなし |

## 例外処理

| 例外 | HTTPステータス | 条件 | レスポンス |
|------|--------------|------|----------|
| ResourceNotFoundException | 404 | ドキュメントが存在しない場合 | ボディなし（HEADのため） |
| ResourceNotFoundException | 404 | ドキュメントのソースが空の場合 | ボディなし（HEADのため） |

## 備考

- 本APIはRestGetSourceActionで処理される。GET /{index}/_source/{id}（ドキュメントソース取得）とHEAD /{index}/_source/{id}（ドキュメントソース存在確認）は同一のハンドラで処理される。
- RestGetSourceAction.javaの70行目で `new Route(HEAD, "/{index}/_source/{id}")` としてHEADルートが登録されている。
- ドキュメント存在確認API（HEAD /{index}/_doc/{id}）との違いは、本APIではドキュメントは存在するがソースが空の場合にも404を返す点である。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | GetResponse.java | `server/src/main/java/org/opensearch/action/get/GetResponse.java` | isExists()とisSourceEmpty()の2つのチェックメソッドを理解する |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestGetSourceAction.java | `server/src/main/java/org/opensearch/rest/action/document/RestGetSourceAction.java` | 70行目でHEADルートが登録されていること、125-133行目のcheckResource()でドキュメント存在とソース存在の2段階チェックを確認する |

**主要処理フロー**:
1. **70行目**: HEADルートを `/{index}/_source/{id}` で登録
2. **79-97行目**: GETと同じパラメータ解析処理
3. **94行目**: client.get()の実行
4. **108-116行目**: buildResponse()でレスポンス構築（HEADのためボディは破棄）
5. **129行目**: `response.isExists() == false` でドキュメント未存在チェック
6. **131行目**: `response.isSourceEmpty()` でソース空チェック

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

```
RestGetSourceAction.prepareRequest()  [HEAD /{index}/_source/{id}]
    |
    +-- GetRequest 構築
    +-- FetchSourceContext 設定
    |
    +-- client.get(getRequest, RestGetSourceResponseListener)
            |
            +-- TransportGetAction
                    |
                    +-- GetResponse
                            |
                            +-- RestGetSourceResponseListener.buildResponse()
                                    |
                                    +-- checkResource()
                                    |   +-- isExists() ? (continue) : ResourceNotFoundException
                                    |   +-- isSourceEmpty() ? ResourceNotFoundException : (continue)
                                    |
                                    +-- [HTTP層でボディ破棄]
                                    +-- HTTP 200 or 404
```

### データフロー図

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

HEAD /{index}/_source/{id}  --> RestGetSourceAction       --> HTTP 200 (存在)
                                   |                          (ボディなし)
                                   v
                             GetRequest構築               --> HTTP 404 (未存在)
                                   |                          (ボディなし)
                                   v
                             TransportGetAction
                                   |
                                   v
                             checkResource()
                             (isExists + isSourceEmpty)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RestGetSourceAction.java | `server/src/main/java/org/opensearch/rest/action/document/RestGetSourceAction.java` | ソース | RESTハンドラ（GET/HEAD両方を処理） |
| 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` | ソース | トランスポートアクション |
| exists_source.json | `rest-api-spec/src/main/resources/rest-api-spec/api/exists_source.json` | 設定 | REST API仕様定義 |
