# 機能設計書 104-高度な検索

## 概要

本ドキュメントは、GitLabの高度な検索（Advanced Search）機能についての機能設計書である。

### 本機能の処理概要

高度な検索は、Elasticsearchを使用したより強力な検索機能を提供する。基本検索と比較して、より高速な全文検索、正規表現検索、コードナビゲーション、検索結果のハイライトなど、エンタープライズ向けの検索機能を実現する。

**業務上の目的・背景**：大規模なGitLabインスタンスにおいて、PostgreSQL全文検索の限界を超える高速かつ高機能な検索を提供する。数千のプロジェクトと数百万のドキュメントを持つ環境で、秒単位での検索結果返却を実現する。

**機能の利用シーン**：
- 大規模コードベース全体での正規表現検索
- リアルタイムに近いインデックス更新による最新コードの検索
- 詳細なフィルタリング（言語、ファイルパス、作成日等）
- コード検索結果のシンタックスハイライト表示
- ファジー検索による入力ミス許容

**主要な処理内容**：
1. 検索クエリの受付とバリデーション
2. Elasticsearchクエリの構築
3. 検索エンジンへのクエリ実行
4. 結果のハイライト処理
5. ファセット（集計）情報の取得
6. ページネーションとソート

**関連システム・外部連携**：
- Elasticsearch / OpenSearch クラスター
- Zoekt（コード検索専用エンジン、オプション）
- Sidekiq（インデックス更新ジョブ）
- Redis（検索クエリキャッシュ）

**権限による制御**：
- 高度な検索はEEライセンスが必要
- インスタンス管理者による有効化設定が必要
- ユーザーのプロジェクトアクセス権限に基づいた結果フィルタリング

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 284 | 検索結果 | 主画面 | 検索結果表示 |

## 機能種別

全文検索 / コード検索 / Elasticsearch連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| search | String | Yes | 検索キーワード | 最大256文字 |
| scope | String | No | 検索スコープ | blobs/issues/merge_requests/notes/wiki_blobs/commits/users/milestones |
| search_type | String | No | 検索タイプ | basic/advanced/zoekt |
| group_id | Integer | No | グループID | グループ内検索時 |
| project_id | Integer | No | プロジェクトID | プロジェクト内検索時 |
| language | Array | No | プログラミング言語フィルタ | コード検索時 |
| sort | String | No | ソート順 | 各スコープで異なる |
| state | String | No | 状態フィルタ | opened/closed等 |

### 入力データソース

- 検索ボックス入力
- 検索結果ページのフィルタUI
- API経由

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| search_results | Array | 検索結果配列 |
| highlight | Hash | ハイライト情報 |
| aggregations | Hash | ファセット集計 |
| total_count | Integer | 総件数 |

### 出力先

- 検索結果画面（HTML）
- JSON API

## 処理フロー

### 処理シーケンス

```
1. 検索リクエスト受付
   └─ SearchController が検索タイプを判定
2. Elasticsearch有効性チェック
   └─ インスタンス設定とライセンス確認
3. クエリ構築
   └─ Elasticsearchクエリ（DSL）の生成
4. Elasticsearch実行
   └─ クラスターへのクエリ送信
5. 結果処理
   └─ ハイライト、ファセット、ページネーション
6. レスポンス返却
   └─ HTML/JSON形式で結果返却
```

### フローチャート

```mermaid
flowchart TD
    A[検索リクエスト] --> B{Advanced Search有効?}
    B -->|No| C[Basic Search実行]
    B -->|Yes| D{search_type指定?}
    D -->|basic| C
    D -->|advanced/zoekt| E[Elasticsearch/Zoektクエリ構築]
    D -->|未指定| F{デフォルト設定}
    F -->|advanced| E
    F -->|basic| C
    E --> G[検索エンジン実行]
    G --> H{結果あり?}
    H -->|Yes| I[ハイライト処理]
    H -->|No| J[空結果返却]
    I --> K[ファセット集計]
    K --> L[結果表示]
    C --> M[PostgreSQL検索]
    M --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-104-01 | EEライセンス必須 | 高度な検索はEnterprise Edition機能 | 全検索 |
| BR-104-02 | インスタンス設定 | 管理者が高度な検索を有効化必要 | 全検索 |
| BR-104-03 | インデックス遅延 | ドキュメント更新からインデックス反映まで遅延あり | 全ドキュメント |
| BR-104-04 | クエリ複雑度制限 | 過度に複雑なクエリは拒否 | 全検索 |

### 計算ロジック

インデックス更新:
- リアルタイムに近いインデックス更新
- バックグラウンドジョブ（Sidekiq）経由
- 大量更新時はバッチ処理

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 検索 | - | - | Elasticsearch経由（DBアクセスなし） |
| 権限チェック | project_authorizations | SELECT | 検索結果フィルタリング用 |

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

高度な検索は主にElasticsearchを使用するため、PostgreSQLへのアクセスは権限チェックなど最小限に抑えられる。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Flash Alert | Elasticsearch接続エラー | 管理者に連絡、基本検索へフォールバック |
| 408 | Request Timeout | 検索タイムアウト | 検索条件を絞る |
| 503 | Service Unavailable | Elasticsearchクラスター障害 | 復旧待ち |

### リトライ仕様

- Elasticsearch接続エラー: 自動リトライ（バックオフ付き）
- タイムアウト: エラー表示、条件を絞って再検索

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

- 検索は読み取り専用操作
- インデックス更新はSidekiqジョブで非同期実行

## パフォーマンス要件

- 大規模コードベースでも秒単位でのレスポンス
- Elasticsearchクラスターのスケーリングにより性能向上可能
- インデックスサイズに応じたシャード分散

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

- プロジェクトアクセス権限に基づく結果フィルタリング
- Elasticsearch通信の暗号化（TLS）
- 機密データのインデックス除外設定可能

## 備考

- GitLab EE専用機能
- Elasticsearch 7.x / 8.x、OpenSearch 1.x / 2.x対応
- Zoektはコード検索専用のオプション検索エンジン

---

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

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

### 推奨読解順序

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

高度な検索のデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | search_controller.rb | `app/controllers/search_controller.rb` | search_type判定ロジック |

**読解のコツ**: 高度な検索はEE機能のため、`prepend_mod_with`で拡張される。CE版のコードベースでは基本的な検索フレームワークのみ確認可能。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | search_controller.rb | `app/controllers/search_controller.rb` | 検索タイプ判定 |

**主要処理フロー**:
- **57行目**: `@search_type = search_type` で検索タイプ取得
- **313-315行目**: `search_type` メソッドで検索サービスから取得

#### Step 3: 検索サービスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | global_service.rb | `app/services/search/global_service.rb` | 基本検索サービス |

**読解のコツ**: EE版では `ee/app/services/search/` 配下に高度な検索用のサービスが実装される。

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

```
SearchController#show
    │
    ├─ search_type 判定
    │      └─ search_service.search_type
    │
    └─ search_service (CE/EE で異なる)
           │
           ├─ [CE] Search::GlobalService
           │      └─ Gitlab::SearchResults (PostgreSQL)
           │
           └─ [EE] Elastic::GlobalService
                  └─ Elasticsearch クエリ実行
                         │
                         ├─ 結果取得
                         ├─ ハイライト
                         └─ ファセット集計
```

### データフロー図

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

検索クエリ (search) ────▶ Search::GlobalService ────────▶ 検索結果
search_type                    │
                              │
                 [EE] Elastic::GlobalService
                              │
                              └─ Elasticsearch Cluster
                                     │
                                     ├─ インデックス検索
                                     ├─ スコアリング
                                     └─ ハイライト生成
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| search_controller.rb | `app/controllers/search_controller.rb` | ソース | HTTPエンドポイント |
| global_service.rb | `app/services/search/global_service.rb` | ソース | 基本検索サービス |
| (EE) elastic_service.rb | `ee/app/services/search/` | ソース | Elasticsearch検索 |
| (EE) zoekt_service.rb | `ee/app/services/search/` | ソース | Zoektコード検索 |
