# 機能設計書 20-検索API

## 概要

本ドキュメントは、OpenSearchの「検索API」機能の設計を記述する。REST APIを通じた検索リクエストの処理（Search API）の全体的な処理仕様を定義する。

### 本機能の処理概要

本機能は、クライアントからの検索リクエストを受け付け、クエリフェーズ（Query Phase）とフェッチフェーズ（Fetch Phase）の2フェーズで検索を実行し、結果を返却するOpenSearchの中心的なAPIである。REST APIの `GET/POST /{index}/_search` エンドポイントを通じて呼び出される。

**業務上の目的・背景**：OpenSearchの最も基本的かつ重要なAPIとして、全文検索、構造化検索、集計、サジェスト等の多様な検索機能を統一的なインターフェースで提供する。分散環境における複数シャード・複数インデックスにまたがる検索のオーケストレーションを担当する。

**機能の利用シーン**：アプリケーションからのテキスト検索、ダッシュボード向けの集計クエリ、検索テンプレートの実行、ドキュメント件数の取得、検索結果のフィルタリング・ソートで利用される。

**主要な処理内容**：
1. 検索リクエストの解析とバリデーション
2. 検索パイプラインによるリクエスト前処理
3. インデックス・シャードの解決とルーティング
4. Query Phase：各シャードでのクエリ実行（マッチドキュメントのID・スコア取得）
5. Reduce Phase：各シャードの結果をコーディネーティングノードで統合・ソート
6. Fetch Phase：上位ドキュメントの実データ取得
7. 検索パイプラインによるレスポンス後処理
8. レスポンス構築と返却

**関連システム・外部連携**：全文検索（No.19）、集計機能（No.31-34）、検索パイプライン（No.45）、サジェスト機能（No.25）、検索プロファイリング（No.29）。リモートクラスタへのクロスクラスタ検索もサポート。

**権限による制御**：アクション名 `indices:data/read/search` に基づくセキュリティ権限チェック。インデックスレベル、ドキュメントレベル、フィールドレベルのセキュリティが適用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 21 | 検索 | 主機能 | REST APIを通じた検索リクエスト処理 |
| 22 | 複数検索 | 補助機能 | 個々の検索リクエストの実行処理 |
| 23 | ドキュメント件数 | 主機能 | クエリに一致するドキュメント数を返す処理 |
| 26 | 検索テンプレート | 主機能 | Mustache言語で事前レンダリングされた検索定義を使用する処理 |
| 29 | ランク評価 | 補助機能 | ランク評価対象の検索を実行する処理 |

## 機能種別

CRUD操作（Read） - 検索API

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| indices | String[] | No | 検索対象インデックス名（省略時は全インデックス） | - |
| source | SearchSourceBuilder | No | 検索定義（query, sort, aggregations等） | - |
| searchType | SearchType | No | 検索タイプ（QUERY_THEN_FETCH/DFS_QUERY_THEN_FETCH） | - |
| routing | String | No | シャードルーティング | - |
| preference | String | No | シャード選択の優先度 | - |
| scroll | TimeValue | No | スクロール検索のキープアライブ時間 | - |
| requestCache | Boolean | No | リクエストキャッシュの使用 | - |
| allowPartialSearchResults | boolean | No | 部分的検索結果を許可するか | - |
| batchedReduceSize | int | No | バッチリデュースサイズ | - |
| maxConcurrentShardRequests | int | No | 同時シャードリクエスト数の上限 | - |
| preFilterShardSize | int | No | シャードプリフィルタサイズ | - |
| cancelAfterTimeInterval | TimeValue | No | 指定時間後にキャンセル | - |
| pipeline | String | No | 検索パイプライン名 | - |

### 入力データソース

REST APIリクエスト（HTTP GET/POST、クエリパラメータ + JSONボディ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| took | long | 検索処理時間（ミリ秒） |
| timed_out | boolean | タイムアウトしたか |
| _shards | Object | シャード処理結果（total, successful, skipped, failed） |
| hits | SearchHits | 検索ヒット結果 |
| hits.total | TotalHits | 総ヒット数 |
| hits.max_score | float | 最大スコア |
| hits.hits[] | SearchHit[] | 個別ヒットドキュメント配列 |
| hits.hits[]._index | String | インデックス名 |
| hits.hits[]._id | String | ドキュメントID |
| hits.hits[]._score | float | 関連性スコア |
| hits.hits[]._source | Object | ドキュメントソース |
| aggregations | Aggregations | 集計結果（該当時） |
| suggest | Suggest | サジェスト結果（該当時） |
| profile | SearchProfileShardResults | プロファイリング結果（該当時） |

### 出力先

REST APIレスポンス（JSON形式）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信・解析
   └─ SearchSourceBuilderによるリクエストボディ解析
2. 検索パイプライン前処理
   └─ SearchPipelineService.resolvePipeline()によるリクエスト変換
3. クエリ書き換え
   └─ Rewriteableインターフェースによるクエリの最適化
4. インデックス・シャード解決
   └─ IndexNameExpressionResolver + OperationRoutingによるシャード特定
5. CanMatchプリフィルタ
   └─ CanMatchPreFilterSearchPhaseでマッチ可能性のないシャードをスキップ
6. Query Phase（分散）
   └─ 各シャードでクエリ実行、TopDocsとAggregations収集
7. Reduce Phase
   └─ コーディネーティングノードで各シャードの結果を統合・ソート
8. Fetch Phase
   └─ 上位ドキュメントの_source等を各シャードから取得
9. 検索パイプライン後処理
   └─ SearchPipelineServiceによるレスポンス変換
10. レスポンス構築・返却
    └─ SearchResponse生成
```

### フローチャート

```mermaid
flowchart TD
    A[Search API リクエスト受信] --> B[検索パイプライン前処理]
    B --> C[クエリ書き換え]
    C --> D[インデックス・シャード解決]
    D --> E[CanMatchプリフィルタ]
    E --> F[Query Phase - 各シャード]
    F --> G[Reduce Phase - 結果統合]
    G --> H[Fetch Phase - ドキュメント取得]
    H --> I[検索パイプライン後処理]
    I --> J[SearchResponse 返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-20-01 | 2フェーズ検索 | QUERY_THEN_FETCH方式で、まずQuery PhaseでドキュメントIDを収集し、次にFetch Phaseで実データを取得 | デフォルト |
| BR-20-02 | DFS検索 | DFS_QUERY_THEN_FETCH方式では、事前にグローバルな統計情報を収集してスコアリング精度を向上 | searchType=DFS_QUERY_THEN_FETCH |
| BR-20-03 | CanMatchプリフィルタ | クエリにマッチする可能性のないシャードをQuery Phase前にスキップ | デフォルト有効 |
| BR-20-04 | タイムアウト自動キャンセル | cancelAfterTimeInterval設定時、指定時間後にタスクを自動キャンセル | cancelAfterTimeInterval設定時 |
| BR-20-05 | リクエストキャッシュ | 集計のみのリクエスト等、結果をキャッシュ可能 | requestCache=true |

### 計算ロジック

Reduce Phaseでは各シャードのTopDocsをマージソートし、グローバルなTopNドキュメントを決定する。集計結果もコーディネーティングノードで統合（reduce）される。

## データベース操作仕様

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| Query Phase | Lucene Index（各シャード） | SELECT | 転置インデックス検索 |
| Fetch Phase | Lucene Index（対象シャード） | SELECT | ドキュメントソース取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | SearchParseException | 検索リクエストの解析エラー | リクエスト構文を修正 |
| 400 | QueryShardException | クエリの解析エラー | クエリ構文を修正 |
| 404 | IndexNotFoundException | 指定インデックスが存在しない | インデックス名を確認 |
| 503 | SearchPhaseExecutionException | 全シャードで検索が失敗 | シャードの状態を確認 |
| 429 | CircuitBreakingException | メモリ制限超過 | リクエストサイズを縮小 |

### リトライ仕様

シャードレベルの障害時はレプリカシャードへフェイルオーバーする。allowPartialSearchResults=trueの場合、一部シャードの失敗を許容。

## トランザクション仕様

読み取り専用操作のためトランザクション制御は不要。スクロール検索やPITを使用しない限り、検索はポイントインタイムの一貫性は保証されない。

## パフォーマンス要件

- maxConcurrentShardRequestsで同時シャードリクエスト数を制御
- CanMatchプリフィルタでマッチしないシャードをスキップ
- リクエストキャッシュにより同一クエリの繰り返し実行を高速化
- CircuitBreakerによるメモリ保護
- Tracerによるテレメトリ情報の収集

## セキュリティ考慮事項

- アクション名 `indices:data/read/search` に対する権限チェック
- インデックスレベル、ドキュメントレベル、フィールドレベルのセキュリティが適用可能
- クロスクラスタ検索時のリモートクラスタへの認証・認可

## 備考

- TransportSearchActionはHandledTransportActionを継承しTransportIndicesResolvingActionを実装
- SearchPipelineServiceにより検索パイプラインが適用される
- PipelinedRequestとしてパイプライン処理が行われる
- CancellableTaskとして実装され、タスクのキャンセルをサポート
- TaskResourceTrackingServiceでリソース使用量を追跡
- MetricsRegistryでメトリクスを記録
- SpanBuilderでトレーシング情報を構築

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SearchAction.java | `server/src/main/java/org/opensearch/action/search/SearchAction.java` | アクション名 `indices:data/read/search` の定義 |
| 1-2 | SearchRequest.java | `server/src/main/java/org/opensearch/action/search/SearchRequest.java` | 検索リクエスト構造 |
| 1-3 | SearchResponse.java | `server/src/main/java/org/opensearch/action/search/SearchResponse.java` | 検索レスポンス構造 |

**読解のコツ**: SearchRequestにはSearchSourceBuilderが含まれ、ここにquery, sort, from, size, aggregations, suggest等の検索パラメータが定義される。SearchResponseはInternalSearchResponseをラップする。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TransportSearchAction.java | `server/src/main/java/org/opensearch/action/search/TransportSearchAction.java` | 検索APIの中枢。HandledTransportActionを継承 |

**主要処理フロー**:
1. **冒頭import文**: OperationRouting, SearchPipelineService, IndicesService, Tracer等への依存
2. リクエスト解析 → パイプライン適用 → インデックス解決 → シャードルーティング → 各フェーズ実行

#### Step 3: 検索フェーズを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AbstractSearchAsyncAction.java | `server/src/main/java/org/opensearch/action/search/AbstractSearchAsyncAction.java` | 非同期検索の基底クラス |
| 3-2 | CanMatchPreFilterSearchPhase.java | `server/src/main/java/org/opensearch/action/search/CanMatchPreFilterSearchPhase.java` | シャードプリフィルタ |
| 3-3 | DfsQueryPhase.java | `server/src/main/java/org/opensearch/action/search/DfsQueryPhase.java` | DFSフェーズ |
| 3-4 | FetchSearchPhase.java | `server/src/main/java/org/opensearch/action/search/FetchSearchPhase.java` | フェッチフェーズ |
| 3-5 | ExpandSearchPhase.java | `server/src/main/java/org/opensearch/action/search/ExpandSearchPhase.java` | 展開フェーズ |

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

```
REST API (GET/POST /{index}/_search)
    |
    +-- TransportSearchAction
           |
           +-- SearchPipelineService.resolvePipeline() ... パイプライン適用
           +-- Rewriteable.rewrite() ... クエリ書き換え
           +-- OperationRouting ... シャード解決
           |
           +-- CanMatchPreFilterSearchPhase ... シャードフィルタ
           +-- AbstractSearchAsyncAction
                  |
                  +-- Query Phase (各シャード)
                  |      └─ QueryPhase.execute()
                  |
                  +-- Reduce Phase (コーディネーティングノード)
                  |      └─ SearchPhaseController.reducedQueryPhase()
                  |
                  +-- Fetch Phase (上位ドキュメントのシャード)
                  |      └─ FetchSearchPhase
                  |
                  +-- SearchPipelineService ... レスポンス後処理
                  |
                  +-- SearchResponse 構築
```

### データフロー図

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

SearchRequest           -->  TransportSearchAction          -->  SearchResponse
 - indices                    |                                   - took
 - source                     +-> パイプライン前処理               - timed_out
   - query                    +-> クエリ書き換え                   - _shards
   - sort                     +-> シャード解決                     - hits
   - from/size                +-> CanMatch                          - total
   - aggregations             +-> Query Phase                       - hits[]
   - suggest                  +-> Reduce Phase                    - aggregations
 - searchType                 +-> Fetch Phase                     - suggest
 - pipeline                   +-> パイプライン後処理               - profile
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SearchAction.java | `server/src/main/java/org/opensearch/action/search/SearchAction.java` | ソース | アクション型定義 |
| TransportSearchAction.java | `server/src/main/java/org/opensearch/action/search/TransportSearchAction.java` | ソース | 検索APIのオーケストレーション |
| AbstractSearchAsyncAction.java | `server/src/main/java/org/opensearch/action/search/AbstractSearchAsyncAction.java` | ソース | 非同期検索基底クラス |
| CanMatchPreFilterSearchPhase.java | `server/src/main/java/org/opensearch/action/search/CanMatchPreFilterSearchPhase.java` | ソース | シャードプリフィルタ |
| DfsQueryPhase.java | `server/src/main/java/org/opensearch/action/search/DfsQueryPhase.java` | ソース | DFSクエリフェーズ |
| FetchSearchPhase.java | `server/src/main/java/org/opensearch/action/search/FetchSearchPhase.java` | ソース | フェッチフェーズ |
| ExpandSearchPhase.java | `server/src/main/java/org/opensearch/action/search/ExpandSearchPhase.java` | ソース | 展開フェーズ |
| ArraySearchPhaseResults.java | `server/src/main/java/org/opensearch/action/search/ArraySearchPhaseResults.java` | ソース | フェーズ結果配列 |
| BottomSortValuesCollector.java | `server/src/main/java/org/opensearch/action/search/BottomSortValuesCollector.java` | ソース | ソート値コレクタ |
| CountedCollector.java | `server/src/main/java/org/opensearch/action/search/CountedCollector.java` | ソース | カウントコレクタ |
| SearchRequest.java | `server/src/main/java/org/opensearch/action/search/SearchRequest.java` | ソース | 検索リクエスト |
| SearchResponse.java | `server/src/main/java/org/opensearch/action/search/SearchResponse.java` | ソース | 検索レスポンス |
