# 機能設計書 24-ストリーミング検索

## 概要

本ドキュメントは、OpenSearchのストリーミング検索機能に関する機能設計書である。検索結果をストリーミング形式で返却する機能を定義する。

### 本機能の処理概要

**業務上の目的・背景**：通常の検索APIでは全結果が揃ってからレスポンスが返却されるため、大量のシャードを持つクエリや遅いシャードがある場合にレスポンス遅延が発生する。ストリーミング検索は結果が利用可能になった時点で順次返却することで、First Byte Time（最初の結果到達までの時間）を短縮し、クライアント側での段階的な結果処理を可能にする。

**機能の利用シーン**：大規模クラスタでの検索応答性の向上、リアルタイムダッシュボードへの逐次データ表示、大量シャードへの検索でレイテンシを改善したい場合などで利用される。

**主要な処理内容**：
1. StreamSearchActionを介してストリーミング検索リクエストを受信する
2. StreamTransportSearchActionがTransportSearchActionを継承し、ストリーミング用の検索非同期アクションを構築する
3. StreamSearchQueryThenFetchAsyncActionが各シャードの結果をストリーミング形式で返却する
4. StreamQueryPhaseResultConsumerがストリーム用の結果集約を行う

**関連システム・外部連携**：StreamTransportServiceおよびStreamSearchTransportServiceを使用したストリーミングトランスポート層を利用する。

**権限による制御**：`indices:data/read/search/stream`アクション名で権限が制御される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングにストリーミング検索の関連画面は定義されていない |

## 機能種別

データ検索（ストリーミング形式）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| 通常のSearchRequestパラメータ | - | - | SearchRequestと同じパラメータを使用 | SearchRequestのバリデーションに準拠 |
| searchType | SearchType | No | 検索タイプ（QUERY_THEN_FETCHのみサポート） | QUERY_THEN_FETCH以外はIllegalStateException |

### 入力データソース

StreamTransportService経由のストリーミングリクエスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| SearchResponse | SearchResponse | 通常のSearchResponseと同じ形式（ストリーミングで返却） |

### 出力先

ストリーミングトランスポートチャネル

## 処理フロー

### 処理シーケンス

```
1. StreamSearchActionリクエスト受信
   └─ StreamTransportServiceを介してリクエストを受信
2. StreamTransportSearchAction.doExecute()
   └─ 親クラスTransportSearchActionのロジックを利用
3. searchAsyncAction()でストリーミング用アクション構築
   └─ StreamSearchQueryThenFetchAsyncActionを生成
4. StreamQueryPhaseResultConsumerで結果集約
   └─ ストリーム用の結果集約ロジック
5. ストリーミング形式で結果を返却
```

### フローチャート

```mermaid
flowchart TD
    A[Stream Search Request] --> B[StreamTransportSearchAction.doExecute]
    B --> C[searchAsyncAction構築]
    C --> D{searchType判定}
    D -->|QUERY_THEN_FETCH| E[StreamSearchQueryThenFetchAsyncAction]
    D -->|preFilter=true| F[IllegalStateException]
    D -->|その他| G[IllegalStateException]
    E --> H[StreamQueryPhaseResultConsumer]
    H --> I[各シャードへクエリ送信]
    I --> J[ストリーミング形式で結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-24-01 | 検索タイプ制限 | ストリーミング検索はQUERY_THEN_FETCHのみサポート | 常時 |
| BR-24-02 | プリフィルタ非対応 | Search pre-filterはストリーミングではサポートされない | 常時 |

### 計算ロジック

特になし。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 検索 | 対象インデックス | SELECT | 通常の検索と同様にLuceneインデックスに対して検索を実行 |

### テーブル別操作詳細

通常のSearchRequestと同様。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 500 | IllegalStateException | searchTypeがQUERY_THEN_FETCH以外 | QUERY_THEN_FETCHを使用する |
| 500 | IllegalStateException | preFilter=trueが指定された | ストリーミング検索ではpreFilterを使用しない |

### リトライ仕様

TransportSearchActionのリトライ仕様に準拠。

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

通常の検索と同様、読み取り専用操作。

## パフォーマンス要件

- ストリーミングにより、First Byte Timeの短縮を実現
- CircuitBreakerServiceによるメモリ使用量の制御

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

- アクション名`indices:data/read/search/stream`による権限制御
- 通常の検索と同様のインデックスレベル権限チェック

## 備考

- 内部APIとしてマーク（@opensearch.internal）
- StreamTransportServiceがnullの場合の対応（@Nullable注釈）
- TransportSearchActionを継承しており、大部分の検索ロジックは親クラスから継承

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | StreamSearchAction.java | `server/src/main/java/org/opensearch/action/search/StreamSearchAction.java` | アクション定義。NAME = "indices:data/read/search/stream" |
| 1-2 | SearchRequest.java | `server/src/main/java/org/opensearch/action/search/SearchRequest.java` | 通常のSearchRequestを流用 |

**読解のコツ**: StreamSearchActionは通常のSearchResponseを返却するActionTypeであり、リクエスト/レスポンスは通常検索と同じ型を使用する。ストリーミングの差分はトランスポート層とアクション構築にある。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | StreamTransportSearchAction.java | `server/src/main/java/org/opensearch/action/search/StreamTransportSearchAction.java` | ストリーミング検索のトランスポートアクション |

**主要処理フロー**:
- **43行目**: TransportSearchActionを継承
- **85-142行目**: searchAsyncAction() - ストリーミング用の非同期アクション構築
- **102-103行目**: preFilter=trueの場合はIllegalStateException
- **105-112行目**: StreamQueryPhaseResultConsumer（ストリーム用結果集約）の構築
- **114-136行目**: QUERY_THEN_FETCHの場合のみStreamSearchQueryThenFetchAsyncActionを生成

#### Step 3: ストリーミング用の非同期アクションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | StreamSearchQueryThenFetchAsyncAction.java | `server/src/main/java/org/opensearch/action/search/StreamSearchQueryThenFetchAsyncAction.java` | ストリーミング版QTFアクション |
| 3-2 | StreamQueryPhaseResultConsumer.java | `server/src/main/java/org/opensearch/action/search/StreamQueryPhaseResultConsumer.java` | ストリーム用結果集約 |
| 3-3 | StreamSearchTransportService.java | `server/src/main/java/org/opensearch/action/search/StreamSearchTransportService.java` | ストリーミング用トランスポートサービス |

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

```
StreamSearchAction (ActionType)
    |
    +-- StreamTransportSearchAction.doExecute() [親クラス継承]
            |
            +-- searchAsyncAction() [オーバーライド]
                    |
                    +-- searchPhaseController.newStreamSearchPhaseResults()
                    |       |
                    |       +-- StreamQueryPhaseResultConsumer
                    |
                    +-- StreamSearchQueryThenFetchAsyncAction
                            |
                            +-- StreamSearchTransportService (シャード通信)
                            |
                            +-- ストリーミングレスポンス返却
```

### データフロー図

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

SearchRequest ──────> StreamTransportSearchAction ──────> SearchResponse
(Stream Transport)        |                           (Streaming Channel)
                          v
                     searchAsyncAction()
                          |
                     StreamSearchQueryThenFetchAsyncAction
                          |
               +──────────+──────────+
               |          |          |
            Shard[0]   Shard[1]   Shard[N]
               |          |          |
               +──────────+──────────+
                          |
                     StreamQueryPhaseResultConsumer
                          |
                     ストリーミング返却
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| StreamSearchAction.java | `server/src/main/java/org/opensearch/action/search/StreamSearchAction.java` | ソース | アクション型定義 |
| StreamTransportSearchAction.java | `server/src/main/java/org/opensearch/action/search/StreamTransportSearchAction.java` | ソース | ストリーミング検索トランスポート |
| StreamSearchQueryThenFetchAsyncAction.java | `server/src/main/java/org/opensearch/action/search/StreamSearchQueryThenFetchAsyncAction.java` | ソース | ストリーミングQTFアクション |
| StreamQueryPhaseResultConsumer.java | `server/src/main/java/org/opensearch/action/search/StreamQueryPhaseResultConsumer.java` | ソース | ストリーム用結果集約 |
| StreamSearchTransportService.java | `server/src/main/java/org/opensearch/action/search/StreamSearchTransportService.java` | ソース | ストリーミングトランスポートサービス |
| StreamSearchActionListener.java | `server/src/main/java/org/opensearch/action/search/StreamSearchActionListener.java` | ソース | ストリーミング検索リスナー |
| TransportSearchAction.java | `server/src/main/java/org/opensearch/action/search/TransportSearchAction.java` | ソース | 親クラス（検索共通ロジック） |
