# 画面設計書 21-検索

## 概要

本ドキュメントは、OpenSearchの検索API（Search API）エンドポイントに関する画面設計書である。Search APIはOpenSearchの最も中核的なAPIであり、Query DSLを使用してインデックスに格納されたドキュメントを検索し、一致する結果を返す。

### 本画面の処理概要

Search APIは、OpenSearchクラスタに対してクエリを発行し、条件に一致するドキュメントを取得するためのRESTエンドポイントである。

**業務上の目的・背景**：検索エンジンの最も基本的かつ重要な機能であり、ユーザーがインデックスに格納されたデータから条件に合致するドキュメントを高速に取得するために必要不可欠である。全文検索、構造化検索、集計（Aggregation）、サジェスト、スコアリングなど多岐にわたる検索機能を単一のAPIで提供する。ログ分析、E-commerce検索、データ可視化、監視アラートなど、あらゆるユースケースの基盤となる。

**画面へのアクセス方法**：HTTPクライアント（curl、Kibana Dev Tools、各種SDKなど）から `GET /_search` または `GET/POST /{index}/_search` エンドポイントにリクエストを送信する。URLパラメータによる簡易クエリ（`q`パラメータ）と、リクエストボディによるQuery DSLの両方に対応する。

**主要な操作・処理内容**：
1. クエリパラメータまたはリクエストボディからQuery DSLを解析し、検索条件を構築する
2. 対象インデックスの特定とシャードルーティングを行い、各シャードに検索クエリを分散実行する
3. 各シャードからの検索結果をコーディネーティングノードで集約し、スコアリング・ソートを行う
4. 集計（Aggregation）、サジェスト、ハイライトなどのオプション処理を実行する
5. 検索パイプラインが指定されている場合はリクエスト・レスポンスの加工処理を行う
6. 結果をJSON形式でクライアントに返却する

**画面遷移**：検索結果からスクロール検索（Scroll API）やPoint in Time（PIT）検索へ遷移可能。検索テンプレートAPI、マルチサーチAPI、Explain APIからも本APIが内部的に呼び出される。

**権限による表示制御**：OpenSearch Security プラグインが有効な場合、インデックスレベル、ドキュメントレベル、フィールドレベルのアクセス制御が適用される。権限不足の場合は403エラーが返却される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 20 | 検索API | 主機能 | REST APIを通じた検索リクエスト処理 |
| 19 | 全文検索 | 補助機能 | Luceneベースのクエリを使用した全文検索エンジン処理 |
| 31 | バケット集計 | 補助機能 | 検索結果に対するバケット集計処理 |
| 32 | メトリクス集計 | 補助機能 | 検索結果に対するメトリクス集計処理 |
| 25 | 検索サジェスト | 補助機能 | 検索リクエスト内のサジェスト処理 |
| 29 | 検索プロファイリング | 補助機能 | 検索クエリの実行時間プロファイリング処理 |
| 45 | 検索パイプライン管理 | 補助機能 | 検索パイプラインによるリクエスト・レスポンスの加工処理 |

## 画面種別

API（検索実行・結果返却）

## URL/ルーティング

| メソッド | パス | 説明 |
|---------|------|------|
| GET/POST | `/_search` | 全インデックスを対象に検索 |
| GET/POST | `/{index}/_search` | 指定インデックスを対象に検索 |

## 入出力項目

### URLパスパラメータ

| パラメータ | 型 | 必須 | 説明 |
|-----------|------|------|------|
| index | list | No | 検索対象のインデックス名（カンマ区切り）。`_all`または省略で全インデックス |

### クエリパラメータ

| パラメータ | 型 | デフォルト | 説明 |
|-----------|------|-----------|------|
| q | string | - | Luceneクエリ文字列構文によるクエリ |
| analyzer | string | - | クエリ文字列で使用するアナライザ |
| analyze_wildcard | boolean | false | ワイルドカード・プレフィックスクエリを分析するか |
| default_operator | enum (AND/OR) | OR | クエリ文字列のデフォルト演算子 |
| df | string | - | クエリ文字列でフィールドプレフィックスがない場合のデフォルトフィールド |
| from | number | 0 | 結果の開始オフセット |
| size | number | 10 | 返却するヒット数 |
| sort | list | - | ソート条件（`<field>:<direction>`のカンマ区切り） |
| _source | list | - | _sourceフィールドの返却制御 |
| _source_excludes | list | - | _sourceから除外するフィールド |
| _source_includes | list | - | _sourceに含めるフィールド |
| stored_fields | list | - | 返却するストアドフィールド |
| docvalue_fields | list | - | docvalue表現で返却するフィールド |
| explain | boolean | false | スコア計算の詳細情報を返却するか |
| version | boolean | false | ドキュメントバージョンを返却するか |
| seq_no_primary_term | boolean | false | シーケンス番号とプライマリタームを返却するか |
| timeout | time | - | 操作タイムアウト |
| terminate_after | number | - | 各シャードで収集する最大ドキュメント数 |
| track_scores | boolean | false | ソートに使用しないスコアも計算・返却するか |
| track_total_hits | boolean | - | クエリに一致するドキュメント総数をトラックするか |
| allow_partial_search_results | boolean | true | 部分的な検索失敗・タイムアウト時にエラーを返すか |
| search_type | enum | query_then_fetch | 検索操作タイプ（query_then_fetch/dfs_query_then_fetch） |
| scroll | time | - | スクロール検索のコンテキスト維持時間 |
| routing | list | - | ルーティング値 |
| preference | string | random | 操作を実行するノード/シャードの優先設定 |
| request_cache | boolean | - | リクエストキャッシュの使用有無 |
| batched_reduce_size | number | 512 | コーディネーティングノードで一度に縮約するシャード結果数 |
| max_concurrent_shard_requests | number | 5 | ノードあたりの並行シャードリクエスト数 |
| pre_filter_shard_size | number | - | シャードプリフィルタのしきい値 |
| rest_total_hits_as_int | boolean | false | hits.totalを整数として返却するか |
| search_pipeline | string | - | 使用する検索パイプライン名 |
| include_named_queries_score | boolean | false | 名前付きクエリのスコアをマップ形式で返却するか |
| ccs_minimize_roundtrips | boolean | true | クロスクラスタ検索のラウンドトリップを最小化するか |
| ignore_unavailable | boolean | false | 利用不可のインデックスを無視するか |
| ignore_throttled | boolean | false | スロットルされたインデックスを無視するか |
| allow_no_indices | boolean | - | ワイルドカード式が具体的なインデックスに解決されない場合に無視するか |
| expand_wildcards | enum | open | ワイルドカード式の展開対象（open/closed/hidden/none/all） |
| lenient | boolean | false | フォーマットベースのクエリ失敗を無視するか |
| suggest_field | string | - | サジェスト対象フィールド |
| suggest_mode | enum | missing | サジェストモード（missing/popular/always） |
| suggest_size | number | 5 | 返却するサジェスト数 |
| suggest_text | string | - | サジェスト対象テキスト |
| stats | list | - | リクエストの統計タグ |
| typed_keys | boolean | false | 集計・サジェスタ名にタイプをプレフィックスするか |

### リクエストボディ

Query DSLによる検索定義。主なフィールド：
- `query`: クエリ定義
- `aggs`/`aggregations`: 集計定義
- `sort`: ソート定義
- `from`/`size`: ページネーション
- `_source`: ソースフィルタリング
- `highlight`: ハイライト定義
- `suggest`: サジェスト定義
- `post_filter`: ポストフィルタ
- `search_after`: サーチアフター
- `pit`: Point in Time指定
- `ext`: 検索パイプライン拡張

## 表示項目

### レスポンスボディ

| フィールド | 型 | 説明 |
|-----------|------|------|
| took | number | 検索にかかった時間（ミリ秒） |
| timed_out | boolean | タイムアウトしたか |
| _shards | object | シャード情報（total, successful, skipped, failed） |
| hits | object | 検索結果 |
| hits.total | object/number | 一致したドキュメント総数 |
| hits.max_score | number | 最大スコア |
| hits.hits | array | ヒットしたドキュメントの配列 |
| hits.hits[]._index | string | インデックス名 |
| hits.hits[]._id | string | ドキュメントID |
| hits.hits[]._score | number | 関連度スコア |
| hits.hits[]._source | object | ドキュメントソース |
| aggregations | object | 集計結果（指定時） |
| suggest | object | サジェスト結果（指定時） |

## イベント仕様

### 1-検索リクエスト実行

クライアントからの検索リクエストを受け付け、以下の流れで処理を行う。

1. `RestSearchAction.prepareRequest()`がRESTリクエストを`SearchRequest`に変換
2. URLパラメータとリクエストボディの解析（`parseSearchRequest`メソッド）
3. `SearchSourceBuilder`によるクエリ構築
4. `SearchAction`を介してトランスポート層で検索を実行
5. コーディネーティングノードが各シャードに検索クエリを分散
6. 各シャードの結果を集約し、`SearchResponse`として返却

### 2-スクロール検索への遷移

`scroll`パラメータが指定された場合、検索コンテキストを維持し、Scroll APIで後続のページを取得可能にする。

### 3-Point in Time検索

リクエストボディに`pit`が指定された場合、特定時点のインデックス状態に対して検索を実行する。`indices`、`routing`、`preference`との併用は不可。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 検索リクエスト実行 | Luceneインデックス | SELECT | 指定インデックスのLuceneセグメントから条件に一致するドキュメントを検索 |

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

#### Luceneインデックス（読み取り専用）

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| SELECT | ドキュメント全体 | Query DSLで指定された検索条件に基づく | 書き込み操作は発生しない |

## メッセージ仕様

| 種別 | メッセージ | 発生条件 |
|------|----------|----------|
| 成功 | HTTPステータス200 + 検索結果JSON | 正常に検索が完了した場合 |
| エラー | `Unsupported search type [xxx]` | search_typeにquery_and_fetchまたはdfs_query_and_fetchが指定された場合 |
| エラー | `terminateAfter must be > 0` | terminate_afterに負の値が指定された場合 |
| エラー | `[rest_total_hits_as_int] cannot be used if the tracking of total hits is not accurate` | rest_total_hits_as_intとtrack_total_hitsの不整合 |
| エラー | `[indices] cannot be used with point in time` | PITとindicesの併用 |
| エラー | `[routing] cannot be used with point in time` | PITとroutingの併用 |
| エラー | `[preference] cannot be used with point in time` | PITとpreferenceの併用 |
| エラー | `[ccs_minimize_roundtrips] cannot be used with point in time` | PITとccs_minimize_roundtripsの併用 |

## 例外処理

| 例外 | HTTPステータス | 説明 |
|------|--------------|------|
| IndexNotFoundException | 404 | 指定されたインデックスが存在しない場合（ignore_unavailableがfalseの場合） |
| SearchPhaseExecutionException | 503 | 検索フェーズの実行中にエラーが発生した場合 |
| IllegalArgumentException | 400 | 不正なパラメータが指定された場合 |
| QueryShardException | 400 | クエリの解析/実行に失敗した場合 |
| SecurityException | 403 | アクセス権限がない場合（Security有効時） |
| CircuitBreakingException | 429 | メモリ制限を超えた場合 |

## 備考

- Search APIはOpenSearchの最も高頻度で使用されるAPIであり、パフォーマンスチューニングが重要である
- `query_and_fetch`および`dfs_query_and_fetch`は内部最適化用であり、REST APIからの指定は禁止されている（RestSearchAction 行227-228）
- Stream Search機能がフィーチャーフラグで有効化されている場合、対応する集計であればストリーミング検索が利用される（行153-166）
- `cancel_after_time_interval`パラメータにより、長時間実行される検索を自動キャンセルできる

---

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

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

### 推奨読解順序

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

まず、検索リクエスト・レスポンスのデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SearchRequest.java | `server/src/main/java/org/opensearch/action/search/SearchRequest.java` | 検索リクエストの全体構造（インデックス、ソース、スクロール、ルーティング等） |
| 1-2 | SearchSourceBuilder.java | `server/src/main/java/org/opensearch/search/builder/SearchSourceBuilder.java` | Query DSLのパース構造（query, aggs, sort, from, size等） |
| 1-3 | SearchResponse.java | `server/src/main/java/org/opensearch/action/search/SearchResponse.java` | 検索レスポンスの構造（hits, aggregations, suggest等） |

**読解のコツ**: `SearchSourceBuilder`は`parseXContent`メソッドでリクエストボディのJSON全体をパースする。各フィールドは`ObjectParser`を使って宣言的に定義されている。

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

処理の起点となるRESTハンドラを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestSearchAction.java | `server/src/main/java/org/opensearch/rest/action/search/RestSearchAction.java` | REST APIエンドポイントの登録と、リクエスト→SearchRequestへの変換処理 |

**主要処理フロー**:
1. **行122-131**: `routes()`でGET/POSTの4パターンのルートを登録
2. **行134-171**: `prepareRequest()`でRESTリクエストを`SearchRequest`に変換
3. **行148-151**: リクエストボディのパース（`parseSearchRequest`呼び出し）
4. **行153-166**: Stream Search対応の分岐処理
5. **行167-170**: 通常の`SearchAction`を実行してレスポンスを返却
6. **行180-257**: `parseSearchRequest()`でURLパラメータとボディを統合的にパース
7. **行263-376**: `parseSearchSource()`でURLパラメータからSearchSourceBuilderへの変換

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

検索リクエストがトランスポート層でどのように処理されるかを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TransportSearchAction.java | `server/src/main/java/org/opensearch/action/search/TransportSearchAction.java` | 検索の分散実行、シャードへのリクエスト配分、結果のマージ処理 |
| 3-2 | SearchService.java | `server/src/main/java/org/opensearch/search/SearchService.java` | 各シャードでの検索実行処理 |

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

```
RestSearchAction.prepareRequest()
    |
    +-- parseSearchRequest()
    |       +-- SearchSourceBuilder.parseXContent()
    |       +-- parseSearchSource()
    |       +-- checkRestTotalHits()
    |       +-- preparePointInTime()  [PIT指定時]
    |
    +-- RestCancellableNodeClient.execute()
            +-- SearchAction / StreamSearchAction
                    +-- TransportSearchAction.doExecute()
                            +-- executeSearch()
                                    +-- SearchService.executeQueryPhase()
                                    +-- SearchService.executeFetchPhase()
```

### データフロー図

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

HTTP Request        -->  RestSearchAction                  -->  HTTP Response (JSON)
  - URL params              |
  - Query body              +-- parseSearchRequest()
  (Query DSL)               |       SearchRequest構築
                            +-- TransportSearchAction
                            |       シャード分散実行
                            +-- SearchService
                            |       Lucene検索実行
                            +-- SearchPhaseController
                                    結果集約・スコアリング
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RestSearchAction.java | `server/src/main/java/org/opensearch/rest/action/search/RestSearchAction.java` | ソース | RESTエンドポイントハンドラ |
| SearchRequest.java | `server/src/main/java/org/opensearch/action/search/SearchRequest.java` | ソース | 検索リクエストデータモデル |
| SearchSourceBuilder.java | `server/src/main/java/org/opensearch/search/builder/SearchSourceBuilder.java` | ソース | Query DSLパーサー・ビルダー |
| SearchResponse.java | `server/src/main/java/org/opensearch/action/search/SearchResponse.java` | ソース | 検索レスポンスデータモデル |
| TransportSearchAction.java | `server/src/main/java/org/opensearch/action/search/TransportSearchAction.java` | ソース | 検索のトランスポート層実行 |
| SearchService.java | `server/src/main/java/org/opensearch/search/SearchService.java` | ソース | シャードレベルの検索実行 |
| search.json | `rest-api-spec/src/main/resources/rest-api-spec/api/search.json` | 設定 | REST API仕様定義 |
