# 機能設計書 19-全文検索

## 概要

本ドキュメントは、OpenSearchの「全文検索」機能の設計を記述する。Luceneベースのクエリを使用した全文検索のクエリフェーズ処理仕様を定義する。

### 本機能の処理概要

本機能は、Apache Luceneの検索エンジンを基盤として、テキストデータに対する全文検索クエリの実行を担当するコア機能である。検索API（No.20）から呼び出され、各シャード上でクエリを実行し、マッチするドキュメントのID・スコア・ソート情報を返却する。

**業務上の目的・背景**：OpenSearchの中核機能として、大量のテキストデータから関連性の高いドキュメントを高速に検索する需要に対応する。転置インデックスを用いた効率的なクエリ実行、TF-IDFやBM25によるスコアリング、多様なクエリ構文のサポートが本機能の存在意義である。

**機能の利用シーン**：テキスト検索（match, multi_match）、フレーズ検索（match_phrase）、ブール演算（bool）、範囲検索（range）、ワイルドカード検索等、OpenSearchの全検索操作の基盤として使用される。検索API、マルチサーチ、Update By Query、Delete By Query等の多くの機能から内部的に呼び出される。

**主要な処理内容**：
1. クエリの書き換え（Rewrite）処理
2. Lucene Queryオブジェクトの構築
3. CollectorManagerを使用したドキュメント収集
4. TopDocsの取得（スコアリング・ソート）
5. 集計（Aggregation）処理の実行
6. サジェスト処理の実行
7. リスコア処理の実行
8. プロファイリング情報の収集

**関連システム・外部連携**：Apache Luceneライブラリ（IndexReader, IndexSearcher等）、集計機能、サジェスト機能、プロファイリング機能。

**権限による制御**：全文検索自体は検索APIを通じて呼び出されるため、検索APIのアクション権限（`indices:data/read/search`）が適用される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 21 | 検索 | 補助機能 | Luceneベースのクエリを使用した全文検索エンジン処理 |
| 13 | クエリによる削除 | 補助機能 | 削除対象ドキュメントを特定するためのクエリ実行 |
| 15 | クエリによる更新 | 補助機能 | 更新対象ドキュメントを特定するためのクエリ実行 |
| 23 | ドキュメント件数 | 補助機能 | 件数カウント対象のクエリ実行処理 |

## 機能種別

計算処理（検索エンジンコア）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| searchContext | SearchContext | Yes | 検索実行コンテキスト（クエリ、ソート、集計等の全設定を含む） | - |
| query | Query | Yes | Lucene Queryオブジェクト | - |
| sort | SortAndFormats | No | ソート設定 | - |
| from | int | No | 結果のオフセット | >= 0 |
| size | int | No | 結果の取得件数 | >= 0 |
| trackTotalHitsUpTo | int | No | 正確なヒット数カウントの上限 | - |
| searchAfter | FieldDoc | No | Search After用のカーソル | - |
| minimumScore | Float | No | 最小スコア閾値 | - |
| terminateAfter | int | No | 早期終了のドキュメント数 | - |

### 入力データソース

SearchContext（検索APIからのコンテキスト情報）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| queryResult | QuerySearchResult | クエリフェーズの結果 |
| queryResult.topDocs | TopDocsAndMaxScore | マッチしたドキュメントのID・スコア・ソート値 |
| queryResult.totalHits | TotalHits | 総ヒット数（正確またはLowerBound） |
| queryResult.aggregations | InternalAggregations | 集計結果（該当時） |
| queryResult.suggest | Suggest | サジェスト結果（該当時） |
| queryResult.profileShardResults | ProfileShardResult | プロファイリング結果（該当時） |

### 出力先

QuerySearchResult（Search APIのクエリフェーズ結果として返却）

## 処理フロー

### 処理シーケンス

```
1. 検索コンテキスト準備
   └─ SearchContextからクエリ、ソート、フィルタの取得
2. クエリ書き換え（Rewrite）
   └─ QueryRewriterによるクエリの最適化・書き換え
3. ソート最適化
   └─ ソートフィールドに基づくearly termination判定
4. CollectorManager構築
   └─ TopDocsCollector, AggregationCollector等の構成
5. Lucene検索実行
   └─ ContextIndexSearcher.search()によるドキュメント収集
6. 集計処理
   └─ AggregationProcessor.postProcess()
7. サジェスト処理
   └─ SuggestProcessor.process()
8. リスコア処理
   └─ RescoreProcessor.execute()
9. プロファイリング結果収集
   └─ プロファイリング有効時の結果集約
10. QuerySearchResult構築・返却
```

### フローチャート

```mermaid
flowchart TD
    A[QueryPhase.execute 開始] --> B[クエリ書き換え]
    B --> C[ソート最適化判定]
    C --> D[CollectorManager構築]
    D --> E[Lucene検索実行]
    E --> F{集計あり?}
    F -->|Yes| G[集計処理]
    F -->|No| H{サジェストあり?}
    G --> H
    H -->|Yes| I[サジェスト処理]
    H -->|No| J{リスコアあり?}
    I --> J
    J -->|Yes| K[リスコア処理]
    J -->|No| L[QuerySearchResult構築]
    K --> L
    L --> M[結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-19-01 | ソート最適化 | プライマリソートフィールドに基づくearly terminationでパフォーマンスを向上（SYS_PROP_REWRITE_SORT設定） | ソート指定時 |
| BR-19-02 | 並行クエリ実行 | ConcurrentQueryPhaseSearcherにより、マルチスレッドでのクエリ実行が可能 | 並行検索有効時 |
| BR-19-03 | タスクキャンセル | 検索タスクがキャンセルされた場合、TaskCancelledExceptionが送出される | タスクキャンセル時 |
| BR-19-04 | 最小スコアフィルタ | minimumScore設定時、指定スコア未満のドキュメントは結果から除外される | minimumScore設定時 |
| BR-19-05 | 早期終了 | terminateAfter設定時、指定ドキュメント数に達したら検索を終了 | terminateAfter設定時 |

### 計算ロジック

BM25スコアリングがデフォルトの関連性スコア計算アルゴリズム。QueryPhaseではLuceneのScorer/Collectorメカニズムを通じてスコアが計算される。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 検索実行 | Lucene Index（シャード） | SELECT | 転置インデックスを使用したドキュメント検索 |

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

#### Lucene Index

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | _id, _score, sort_values | Lucene Queryマッチ条件 | 読み取り専用 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | QueryPhaseExecutionException | クエリ実行中のエラー | クエリ構文を修正 |
| 400 | QueryShardException | シャード上でのクエリ解析エラー | クエリを修正 |
| 429 | TaskCancelledException | 検索タスクのキャンセル | リクエストを再送 |

### リトライ仕様

クエリフェーズ自体にはリトライ機能はない。シャードレベルの障害は検索APIのフェイルオーバーメカニズムで処理される。

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

読み取り専用操作のためトランザクション制御は不要。

## パフォーマンス要件

- ソート最適化（SYS_PROP_REWRITE_SORT）によるearly terminationで大幅なパフォーマンス向上
- ConcurrentQueryPhaseSearcherによるマルチスレッド検索
- EWMATrackingThreadPoolExecutorによるスレッドプール効率の追跡
- CollectorManager方式による効率的なメモリ使用

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

- 検索APIのアクション権限に依存
- フィールドレベルセキュリティが適用される場合、結果にフィルタリングが適用される

## 備考

- QueryPhaseは `@PublicApi(since = "1.0.0")` としてマークされた公開APIクラス
- DEFAULT_QUERY_PHASE_SEARCHERはDefaultQueryPhaseSearcherインスタンス
- QueryPhaseSearcherインターフェースによりプラグインがクエリ実行をカスタマイズ可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | QuerySearchResult.java | `server/src/main/java/org/opensearch/search/query/QuerySearchResult.java` | クエリフェーズの結果構造。TopDocs, Aggregations, Suggest等を保持 |
| 1-2 | QuerySearchRequest.java | `server/src/main/java/org/opensearch/search/query/QuerySearchRequest.java` | クエリフェーズのリクエスト構造 |

**読解のコツ**: OpenSearchの検索はQuery Phase（ドキュメントID+スコア取得）とFetch Phase（ドキュメントソース取得）の2フェーズで構成される。全文検索機能はQuery Phaseに相当する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | QueryPhase.java | `server/src/main/java/org/opensearch/search/query/QueryPhase.java` | クエリフェーズの実行エントリーポイント |

**主要処理フロー**:
1. **96行目**: QueryPhaseクラスの定義。@PublicApi(since = "1.0.0")
2. **98-99行目**: SYS_PROP_REWRITE_SORTのシステムプロパティ設定
3. **100行目**: DEFAULT_QUERY_PHASE_SEARCHERの定義

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | QueryPhaseSearcher.java | `server/src/main/java/org/opensearch/search/query/QueryPhaseSearcher.java` | 検索実行のインターフェース |
| 3-2 | ConcurrentQueryPhaseSearcher.java | `server/src/main/java/org/opensearch/search/query/ConcurrentQueryPhaseSearcher.java` | 並行検索の実装 |
| 3-3 | TopDocsCollectorContext.java | `server/src/main/java/org/opensearch/search/query/TopDocsCollectorContext.java` | TopDocs収集のコンテキスト |
| 3-4 | QueryCollectorContext.java | `server/src/main/java/org/opensearch/search/query/QueryCollectorContext.java` | コレクタコンテキストの構成 |

#### Step 4: 補助処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | QueryRewriter.java | `server/src/main/java/org/opensearch/search/query/QueryRewriter.java` | クエリ書き換え |
| 4-2 | EarlyTerminatingCollector.java | `server/src/main/java/org/opensearch/search/query/EarlyTerminatingCollector.java` | 早期終了コレクタ |

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

```
SearchService.executeQueryPhase()
    |
    +-- QueryPhase.execute(SearchContext)
           |
           +-- QueryRewriter.rewrite() ... クエリ書き換え
           |
           +-- QueryPhaseSearcher.searchWith()
           |      |
           |      +-- ContextIndexSearcher.search(Query, CollectorManager)
           |             |
           |             +-- Lucene IndexReader/IndexSearcher
           |
           +-- AggregationProcessor.postProcess() ... 集計
           +-- SuggestProcessor.process() ... サジェスト
           +-- RescoreProcessor.execute() ... リスコア
```

### データフロー図

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

SearchContext          -->  QueryPhase                    -->  QuerySearchResult
 - query                    +-> QueryRewriter                  - topDocs
 - sort                     +-> ContextIndexSearcher           - totalHits
 - aggregations             +-> AggregationProcessor           - aggregations
 - suggest                  +-> SuggestProcessor               - suggest
 - rescore                  +-> RescoreProcessor               - profileResults
 - profile
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| QueryPhase.java | `server/src/main/java/org/opensearch/search/query/QueryPhase.java` | ソース | クエリフェーズ実行 |
| QueryPhaseSearcher.java | `server/src/main/java/org/opensearch/search/query/QueryPhaseSearcher.java` | ソース | 検索実行インターフェース |
| QueryPhaseSearcherWrapper.java | `server/src/main/java/org/opensearch/search/query/QueryPhaseSearcherWrapper.java` | ソース | 検索実行ラッパー |
| ConcurrentQueryPhaseSearcher.java | `server/src/main/java/org/opensearch/search/query/ConcurrentQueryPhaseSearcher.java` | ソース | 並行検索実装 |
| QuerySearchResult.java | `server/src/main/java/org/opensearch/search/query/QuerySearchResult.java` | ソース | クエリ結果 |
| QuerySearchRequest.java | `server/src/main/java/org/opensearch/search/query/QuerySearchRequest.java` | ソース | クエリリクエスト |
| QueryPhaseExecutionException.java | `server/src/main/java/org/opensearch/search/query/QueryPhaseExecutionException.java` | ソース | 実行例外 |
| TopDocsCollectorContext.java | `server/src/main/java/org/opensearch/search/query/TopDocsCollectorContext.java` | ソース | TopDocs収集 |
| QueryCollectorContext.java | `server/src/main/java/org/opensearch/search/query/QueryCollectorContext.java` | ソース | コレクタ構成 |
| QueryRewriter.java | `server/src/main/java/org/opensearch/search/query/QueryRewriter.java` | ソース | クエリ書き換え |
| EarlyTerminatingCollector.java | `server/src/main/java/org/opensearch/search/query/EarlyTerminatingCollector.java` | ソース | 早期終了 |
| EarlyTerminatingCollectorManager.java | `server/src/main/java/org/opensearch/search/query/EarlyTerminatingCollectorManager.java` | ソース | 早期終了マネージャ |
| ReduceableSearchResult.java | `server/src/main/java/org/opensearch/search/query/ReduceableSearchResult.java` | ソース | リデュース可能な検索結果 |
| ScrollQuerySearchResult.java | `server/src/main/java/org/opensearch/search/query/ScrollQuerySearchResult.java` | ソース | スクロール検索結果 |
