# 画面設計書 284-検索結果

## 概要

本ドキュメントは、GitLabの検索結果画面の設計を記載したものである。

### 本画面の処理概要

**業務上の目的・背景**：検索機能は、GitLab内のプロジェクト、課題、マージリクエスト、コード、ユーザーなど、様々なリソースを横断的に検索するための機能である。検索結果画面は、ユーザーが入力した検索クエリに対して、該当するリソースを一覧表示し、目的の情報に素早くアクセスできるようにする。大規模なコードベースやプロジェクト群から必要な情報を効率的に見つけ出すという業務ニーズに対応する。

**画面へのアクセス方法**：ナビゲーションバーの検索ボックスに検索クエリを入力してEnterキーを押すか、検索ボックスで表示されるオートコンプリート結果から「Search for ...」を選択する。URL直接アクセスの場合は `/search?search=キーワード` にアクセスする。

**主要な操作・処理内容**：
1. 検索結果を一覧表示する（スコープ別）
2. スコープを切り替える（Projects/Issues/Merge requests/Code/Users等）
3. 検索結果をフィルタリングする（状態、ラベル、言語等）
4. 検索対象範囲を変更する（グローバル/グループ/プロジェクト）
5. 検索結果をソートする
6. 検索結果から各リソースの詳細画面に遷移する
7. ページネーションで結果を閲覧する

**画面遷移**：
- 遷移元：ナビゲーションバー検索、各画面の検索機能
- 遷移先：プロジェクト詳細、課題詳細、MR詳細、ファイル表示、ユーザープロフィール等

**権限による表示制御**：
- 匿名ユーザー：設定により許可/拒否（global_search_block_anonymous_searches_enabled）
- グローバル検索：スコープ別に有効/無効設定可能
- 検索結果はユーザーのアクセス権限に基づきフィルタリング

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 102 | グローバル検索 | 主機能 | 検索結果の表示処理 |
| 103 | プロジェクト内検索 | 補助機能 | プロジェクトスコープでの検索 |
| 104 | 高度な検索 | 補助機能 | 高度な検索オプション |

## 画面種別

一覧

## URL/ルーティング

| メソッド | パス | コントローラー#アクション | 説明 |
|----------|------|---------------------------|------|
| GET | `/search` | `search#show` | 検索結果表示 |
| GET | `/search/count` | `search#count` | 検索件数取得（Ajax） |
| GET | `/search/autocomplete` | `search#autocomplete` | オートコンプリート |

## 入出力項目

| 項目名 | 項目ID | データ型 | 必須 | 説明 |
|--------|--------|----------|------|------|
| 検索クエリ | search | String | Yes | 検索キーワード |
| スコープ | scope | String | No | 検索対象（projects/issues/merge_requests/blobs/commits/wiki_blobs/notes/milestones/users） |
| プロジェクトID | project_id | Integer | No | プロジェクト限定検索時 |
| グループID | group_id | Integer | No | グループ限定検索時 |
| 状態 | state | String | No | open/closed/merged等 |
| 機密フラグ | confidential | Boolean | No | 機密イシューのフィルタ |
| 言語 | language | Array | No | プログラミング言語フィルタ |
| ページ | page | Integer | No | ページ番号 |
| ソート | sort | String | No | ソート順（created_desc等） |

## 表示項目

| 項目名 | 説明 |
|--------|------|
| 検索ボックス | 検索クエリの入力・編集 |
| スコープタブ | 検索対象タイプの切り替え（件数表示付き） |
| フィルタサイドバー | 状態、言語等のフィルタ条件 |
| 検索結果一覧 | 検索結果のリスト表示 |
| 検索結果件数 | 該当件数の表示 |
| ハイライト | 検索キーワードのハイライト表示 |
| ページネーション | ページ切り替え |
| ソートオプション | 並び順の変更 |

## イベント仕様

### 1-スコープタブ切り替え

**トリガー**：スコープタブ（Projects/Issues等）をクリック

**処理フロー**：
1. 選択されたスコープでURLを更新
2. 該当スコープの検索結果を取得
3. 結果一覧を更新表示

### 2-フィルタ適用

**トリガー**：サイドバーでフィルタ条件を選択

**処理フロー**：
1. フィルタ条件をURLパラメータに追加
2. フィルタ条件を適用した検索を実行
3. 結果一覧を更新

### 3-検索結果クリック

**トリガー**：検索結果の項目をクリック

**処理フロー**：
1. 該当リソースの詳細画面へ遷移
2. コード検索の場合：ファイル表示画面へ遷移（該当行ハイライト）

### 4-ページネーション

**トリガー**：ページ番号または前後ボタンをクリック

**処理フロー**：
1. 指定ページの検索結果を取得
2. 結果一覧を更新

### 5-コミットへのリダイレクト

**トリガー**：検索クエリがコミットSHAの場合（プロジェクトコンテキスト）

**処理フロー**：
1. 完全なコミットSHAかチェック
2. 該当コミットが存在するかチェック
3. 存在する場合：コミット詳細画面へ自動リダイレクト
4. 「検索結果を見る」リンクを表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 検索実行 | - | SELECT | 各種テーブルからの検索 |
| 検索実行 | - | - | Elasticsearch/Zoekt（有効時） |

### 検索対象テーブル（basicモード）

| スコープ | 対象テーブル/インデックス |
|----------|-------------------------|
| projects | projects |
| issues | issues |
| merge_requests | merge_requests |
| milestones | milestones |
| users | users |
| blobs | Gitaly（Git grep） |
| wiki_blobs | Gitaly（Wiki Git grep） |
| commits | Gitaly（Git log） |
| notes | notes |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| MSG001 | 情報 | %{count} %{scope} for term '%{term}' | 検索結果あり時 |
| MSG002 | 情報 | %{scope} results for term '%{term}' | 件数不明時（without_count） |
| MSG003 | 情報 | You have been redirected to the only result; see the search results instead. | コミットへの自動リダイレクト時 |
| MSG004 | 警告 | Search query is too long. Maximum is %{count} characters. | 文字数制限超過時 |
| MSG005 | 警告 | Search query has too many terms. Maximum is %{count}. | 検索語数制限超過時 |
| MSG006 | 警告 | Global Search is disabled for this scope | 無効なスコープ |

## 例外処理

| 例外条件 | 画面表示・動作 |
|----------|---------------|
| 検索クエリが空 | 検索結果なしを表示 |
| 文字数制限超過 | 警告メッセージを表示、検索実行せず |
| 検索語数制限超過 | 警告メッセージを表示、検索実行せず |
| タイムアウト | タイムアウトエラー画面を表示 |
| 権限なしの結果 | 結果から除外（redacted） |
| レート制限超過 | 429エラー |
| スコープ無効 | Global Search is disabled メッセージ |

## 備考

- 検索文字数制限：`Gitlab::Search::Params::SEARCH_CHAR_LIMIT` (デフォルト4096文字)
- 検索語数制限：`Gitlab::Search::Params::SEARCH_TERM_LIMIT` (デフォルト64語)
- ページあたり件数：デフォルト20件、最大200件
- キャッシュ：件数取得APIは1分間ブラウザキャッシュ
- 高度な検索（Elasticsearch）が有効な場合、検索機能が強化される
- Zoektが有効な場合、コード検索が強化される

---

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

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

### 推奨読解順序

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

検索パラメータと結果の構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | search_service.rb | `app/services/search_service.rb` | 検索サービスの構造、スコープ処理 |
| 1-2 | params.rb | `lib/gitlab/search/params.rb` | 検索パラメータのバリデーション |

**読解のコツ**: `SearchService` は検索のファサードクラスで、スコープに応じて適切なサービス（ProjectService/GroupService/GlobalService）に委譲する。

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

コントローラーの処理フローを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | search_controller.rb | `app/controllers/search_controller.rb` | showアクション、count、autocomplete |
| 2-2 | show.html.haml | `app/views/search/show.html.haml` | ビューテンプレートの構造 |

**主要処理フロー**:
1. **行48-69**: `show` アクションでSearchServiceを初期化
2. **行58**: 検索クエリのバリデーション
3. **行60-61**: コミットへの自動リダイレクトチェック
4. **行68**: `haml_search_results` で検索実行
5. **行152-180**: 検索結果取得とSLI記録

#### Step 3: ビューレイヤーを理解する

Vue.jsコンポーネントとの連携を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | show.html.haml | `app/views/search/show.html.haml` | Vue.jsマウントポイント |
| 3-2 | _results.html.haml | `app/views/search/_results.html.haml` | 結果表示パーシャル |

**主要データ属性**（行22-34）:
- `navigation_json`: スコープナビゲーション情報
- `search_type`: 検索タイプ（basic/advanced）
- `advanced_search_available`: 高度な検索の有効フラグ
- `zoekt_available`: Zoektの有効フラグ
- `search_level`: 検索レベル（global/group/project）
- `group_initial_json`, `project_initial_json`: コンテキスト情報

#### Step 4: 検索実行サービスを理解する

各スコープの検索実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | global_service.rb | `app/services/search/global_service.rb` | グローバル検索 |
| 4-2 | project_service.rb | `app/services/search/project_service.rb` | プロジェクト内検索 |
| 4-3 | group_service.rb | `app/services/search/group_service.rb` | グループ内検索 |

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

```
SearchController#show
    │
    ├─ search_service（遅延初期化）
    │      └─ SearchService.new(current_user, params)
    │
    ├─ search_term_valid?
    │      ├─ valid_query_length?
    │      └─ valid_terms_count?
    │
    ├─ check_single_commit_result?（コミットリダイレクト）
    │
    └─ haml_search_results
           │
           ├─ @search_service_presenter.search_results
           │      └─ SearchService#search_results
           │             └─ search_service.execute
           │                    │
           │                    ├─ Search::ProjectService.execute（project指定時）
           │                    ├─ Search::GroupService.execute（group指定時）
           │                    └─ Search::GlobalService.execute（それ以外）
           │
           └─ @search_service_presenter.search_objects
                  └─ redact_unauthorized_results
```

### データフロー図

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

検索クエリ ───▶ SearchController#show
(search, scope,           │
group_id, project_id)     ▼
                    SearchService
                          │
        ┌─────────────────┼─────────────────┐
        ▼                 ▼                 ▼
   GlobalService    GroupService     ProjectService
        │                 │                 │
        ▼                 ▼                 ▼
   GitLab DB /      GitLab DB /       GitLab DB /
   Elasticsearch    Elasticsearch     Elasticsearch /
                                      Gitaly (Code)
        │                 │                 │
        └─────────────────┼─────────────────┘
                          ▼
                    SearchResults
                          │
                          ▼
                    redact_unauthorized_results
                          │
                          ▼
                    検索結果一覧 ───▶ 各リソース詳細画面
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| show.html.haml | `app/views/search/show.html.haml` | テンプレート | 検索結果画面のビュー |
| _results.html.haml | `app/views/search/_results.html.haml` | テンプレート | 結果表示パーシャル |
| search_controller.rb | `app/controllers/search_controller.rb` | コントローラー | 検索コントローラー |
| search_service.rb | `app/services/search_service.rb` | サービス | 検索ファサードサービス |
| global_service.rb | `app/services/search/global_service.rb` | サービス | グローバル検索 |
| project_service.rb | `app/services/search/project_service.rb` | サービス | プロジェクト内検索 |
| group_service.rb | `app/services/search/group_service.rb` | サービス | グループ内検索 |
| params.rb | `lib/gitlab/search/params.rb` | ライブラリ | パラメータバリデーション |
| search_helper.rb | `app/helpers/search_helper.rb` | ヘルパー | 検索ヘルパーメソッド |
