# 画面設計書 22-複数検索

## 概要

本ドキュメントは、OpenSearchのMulti Search API（`_msearch`）エンドポイントに関する画面設計書である。1回のHTTPリクエストで複数の検索リクエストを一括実行し、それぞれの検索結果をまとめて返却する。

### 本画面の処理概要

Multi Search APIは、複数の独立した検索リクエストを1つのHTTPリクエストにバンドルして送信し、各検索結果を配列形式で返却するAPIである。

**業務上の目的・背景**：ダッシュボード表示やレポート生成など、同時に複数の異なるクエリを実行する必要がある場面で、HTTPリクエストのオーバーヘッドを削減するために使用される。ネットワークレイテンシの最小化と、クライアント側のコード簡素化に貢献する。

**画面へのアクセス方法**：HTTPクライアントから `GET/POST /_msearch` または `GET/POST /{index}/_msearch` エンドポイントにNDJSON（Newline Delimited JSON）形式のリクエストボディを送信する。

**主要な操作・処理内容**：
1. NDJSON形式のリクエストボディを解析し、メタデータ行とクエリ本体行のペアを抽出する
2. 各ペアから個別のSearchRequestを構築する
3. 各SearchRequestを並行して実行する（max_concurrent_searchesで並行数を制御可能）
4. 全検索結果を配列にまとめてレスポンスとして返却する

**画面遷移**：各個別の検索は内部的にSearch API（No.21）と同じ処理パスを使用する。検索テンプレートとの組み合わせはMulti Search Template API（No.27）で提供される。

**権限による表示制御**：各検索リクエストに対して個別にインデックスレベルの権限チェックが行われる。権限不足の検索は個別にエラーレスポンスを返す。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 21 | マルチサーチ | 主機能 | 1リクエストで複数の検索を実行するMulti Search API処理 |
| 20 | 検索API | 補助機能 | 個々の検索リクエストの実行処理 |

## 画面種別

API（複数検索一括実行・結果返却）

## URL/ルーティング

| メソッド | パス | 説明 |
|---------|------|------|
| GET/POST | `/_msearch` | デフォルトインデックスなしで複数検索 |
| GET/POST | `/{index}/_msearch` | デフォルトインデックスを指定して複数検索 |

## 入出力項目

### URLパスパラメータ

| パラメータ | 型 | 必須 | 説明 |
|-----------|------|------|------|
| index | list | No | デフォルトとして使用するインデックス名（カンマ区切り） |

### クエリパラメータ

| パラメータ | 型 | デフォルト | 説明 |
|-----------|------|-----------|------|
| search_type | enum | query_then_fetch | 検索操作タイプ |
| max_concurrent_searches | number | - | 同時実行する最大検索数 |
| typed_keys | boolean | false | 集計・サジェスタ名にタイプをプレフィックスするか |
| pre_filter_shard_size | number | - | シャードプリフィルタのしきい値 |
| max_concurrent_shard_requests | number | 5 | ノードあたりの並行シャードリクエスト数 |
| rest_total_hits_as_int | boolean | false | hits.totalを整数として返却するか |
| ccs_minimize_roundtrips | boolean | true | クロスクラスタ検索のラウンドトリップを最小化するか |

### リクエストボディ（NDJSON形式、必須）

メタデータ行とクエリ本体行のペアをnewlineで区切って繰り返す（bulk serialize形式）。

```
{"index": "index1"}
{"query": {"match": {"field": "value"}}}
{"index": "index2"}
{"query": {"match_all": {}}}
```

## 表示項目

### レスポンスボディ

| フィールド | 型 | 説明 |
|-----------|------|------|
| responses | array | 各検索のレスポンス配列 |
| responses[].took | number | 各検索にかかった時間（ミリ秒） |
| responses[].timed_out | boolean | タイムアウトしたか |
| responses[].hits | object | 検索結果 |
| responses[].status | number | HTTPステータスコード |
| responses[].error | object | エラー情報（エラー発生時） |

## イベント仕様

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

1. `RestMultiSearchAction.prepareRequest()`がリクエストを受信
2. `parseRequest()`でNDJSON形式のボディを解析し、`MultiSearchRequest`を構築
3. `parseMultiLineRequest()`で各行ペアを`SearchRequest`に変換
4. `MultiSearchAction`を介して各検索を並行実行
5. 全結果を`MultiSearchResponse`としてまとめて返却

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 複数検索実行 | Luceneインデックス | SELECT | 各検索リクエストで指定されたインデックスのドキュメントを検索 |

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

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

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| SELECT | ドキュメント全体 | 各SearchRequestのQuery DSL条件に基づく | 書き込み操作は発生しない |

## メッセージ仕様

| 種別 | メッセージ | 発生条件 |
|------|----------|----------|
| 成功 | HTTPステータス200 + 検索結果配列JSON | 正常に全検索が完了した場合（個別エラーはresponses内に含む） |
| エラー | 各検索の個別エラー | 各検索リクエスト内で発生したエラーは個別のレスポンスに含まれる |

## 例外処理

| 例外 | HTTPステータス | 説明 |
|------|--------------|------|
| IllegalArgumentException | 400 | リクエストボディの形式が不正な場合 |
| SecurityException | 403 | アクセス権限がない場合（全体レベル） |

## 備考

- リクエストボディはNDJSON（Newline Delimited JSON）形式であり、Content-Typeは`application/x-ndjson`が推奨される
- ボディの最終行もnewlineで終わる必要がある
- `cancel_after_time_interval`は個別検索レベルとマルチ検索レベルの両方で設定可能で、個別設定が優先される（RestMultiSearchAction 行171-173）
- `allowExplicitIndex`設定により、メタデータ行でのインデックス指定を制御できる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MultiSearchRequest.java | `server/src/main/java/org/opensearch/action/search/MultiSearchRequest.java` | 複数SearchRequestを保持するコンテナ構造 |
| 1-2 | MultiSearchResponse.java | `server/src/main/java/org/opensearch/action/search/MultiSearchResponse.java` | 複数レスポンスの配列構造 |

**読解のコツ**: `MultiSearchRequest.readMultiLineFormat()`がNDJSON形式のパース処理の核心部分である。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestMultiSearchAction.java | `server/src/main/java/org/opensearch/rest/action/search/RestMultiSearchAction.java` | RESTハンドラとNDJSONパース処理 |

**主要処理フロー**:
1. **行94-101**: `routes()`で4パターンのルートを登録
2. **行110-116**: `prepareRequest()`でMultiSearchRequestを構築し実行
3. **行121-176**: `parseRequest()`でNDJSONボディをパースし各SearchRequestを構築
4. **行181-209**: `parseMultiLineRequest()`で各行ペアの解析

#### Step 3: 個別検索の実行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TransportMultiSearchAction.java | `server/src/main/java/org/opensearch/action/search/TransportMultiSearchAction.java` | 複数検索の並行実行制御 |

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

```
RestMultiSearchAction.prepareRequest()
    |
    +-- parseRequest()
    |       +-- parseMultiLineRequest()
    |       |       +-- MultiSearchRequest.readMultiLineFormat()
    |       +-- RestSearchAction.checkRestTotalHits() [各リクエスト]
    |
    +-- RestCancellableNodeClient.execute()
            +-- MultiSearchAction
                    +-- TransportMultiSearchAction.doExecute()
                            +-- SearchAction [各個別検索]
```

### データフロー図

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

HTTP Request        -->  RestMultiSearchAction              -->  HTTP Response (JSON)
  - NDJSON body             |
  (メタデータ+クエリ          +-- parseMultiLineRequest()
   のペア繰り返し)            |       MultiSearchRequest構築
                            +-- TransportMultiSearchAction
                            |       並行検索実行
                            +-- 各SearchAction
                                    結果配列に集約
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RestMultiSearchAction.java | `server/src/main/java/org/opensearch/rest/action/search/RestMultiSearchAction.java` | ソース | RESTエンドポイントハンドラ |
| MultiSearchRequest.java | `server/src/main/java/org/opensearch/action/search/MultiSearchRequest.java` | ソース | 複数検索リクエストデータモデル |
| MultiSearchResponse.java | `server/src/main/java/org/opensearch/action/search/MultiSearchResponse.java` | ソース | 複数検索レスポンスデータモデル |
| TransportMultiSearchAction.java | `server/src/main/java/org/opensearch/action/search/TransportMultiSearchAction.java` | ソース | 複数検索のトランスポート層実行 |
| msearch.json | `rest-api-spec/src/main/resources/rest-api-spec/api/msearch.json` | 設定 | REST API仕様定義 |
