# 機能設計書 33-エントリ検索

## 概要

全コレクション横断でのエントリ全文検索機能について記述する。バックエンドまたは統合検索プロバイダ（Algolia等）を使用してエントリを検索し、結果を返却する。

### 本機能の処理概要

エントリ検索機能は、ユーザーがCMS管理画面のヘッダーまたはコレクション検索コンポーネントから検索クエリを入力した際に、全コレクションまたは指定コレクション内のエントリを全文検索する機能である。Redux Thunkアクションとして実装されており、非同期でバックエンドAPIまたは統合プロバイダを呼び出す。

**業務上の目的・背景**：CMSで管理するコンテンツが増加すると、目的のエントリを素早く見つけることが困難になる。エントリ検索機能を提供することで、コンテンツ編集者がコレクションを横断して必要なエントリに迅速にアクセスできるようにする。

**機能の利用シーン**：CMS管理画面のヘッダーの検索バーに検索語を入力した際に実行される。コレクション一覧画面からコレクション内検索を行う場合や、コレクション検索結果画面での表示にも使用される。

**主要な処理内容**：
1. 重複検索の検出と抑止（同一検索語・同一コレクション・同一ページの検索を防止）
2. 統合検索プロバイダの存在チェック
3. 統合プロバイダ経由またはバックエンド経由での検索実行
4. 検索結果のReduxストアへの格納
5. ページネーション対応（統合プロバイダ使用時）

**関連システム・外部連携**：統合検索プロバイダ（Algolia等）が設定されている場合はそちらを使用。未設定の場合はGitバックエンドの検索機能を直接使用。

**権限による制御**：認証済みユーザーのみ検索可能（バックエンドAPIへのアクセスにトークンが必要）。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | コレクション一覧画面 | 補助機能 | サイドバーのCollectionSearchコンポーネントによるコレクション内検索 |
| 4 | コレクション検索結果画面 | 主機能 | 検索クエリに基づくエントリ全文検索結果の表示 |

## 機能種別

検索処理 / データ取得

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| searchTerm | string | Yes | 検索語 | なし |
| searchCollections | string[] | No | 検索対象コレクション名の配列（省略時は全コレクション） | なし |
| page | number | No | ページ番号（デフォルト: 0） | なし |

### 入力データソース

- ユーザーの検索入力（ヘッダー検索バー、コレクション検索コンポーネント）
- Reduxストア（state.collections、state.search、state.integrations）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| entries | EntryValue[] | 検索にマッチしたエントリの配列 |
| page | number | 現在のページ番号（ページネーション用） |

### 出力先

- Reduxストア（SEARCH_ENTRIES_SUCCESS / SEARCH_ENTRIES_FAILURE アクション経由）

## 処理フロー

### 処理シーケンス

```
1. searchEntries アクションの発行
   └─ searchTerm, searchCollections, page を受け取る
2. 重複検索チェック
   └─ isFetching && 同一searchTerm && 同一collections && 同一page の場合はスキップ
3. SEARCH_ENTRIES_REQUEST アクション発行
   └─ 検索開始を通知
4. 検索プロバイダの決定
   ├─ 統合プロバイダ（Algolia等）が存在する場合
   │   └─ getIntegrationProvider().search() を実行
   └─ 統合プロバイダが存在しない場合
       └─ backend.search() を実行
5. 検索結果の処理
   ├─ 成功: SEARCH_ENTRIES_SUCCESS（entries, pagination）
   └─ 失敗: SEARCH_ENTRIES_FAILURE（error）
```

### フローチャート

```mermaid
flowchart TD
    A[searchEntries呼び出し] --> B{重複検索?}
    B -->|Yes| C[処理なし return]
    B -->|No| D[SEARCH_ENTRIES_REQUEST発行]
    D --> E{統合プロバイダ存在?}
    E -->|Yes| F[integrationProvider.search]
    E -->|No| G[backend.search]
    F --> H{成功?}
    G --> H
    H -->|Yes| I[SEARCH_ENTRIES_SUCCESS]
    H -->|No| J[SEARCH_ENTRIES_FAILURE]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-33-01 | 重複検索抑止 | 同一条件（searchTerm, collections, page）の検索が進行中の場合、新たな検索を発行しない | isFetchingがtrueの場合 |
| BR-33-02 | コレクション省略時の全検索 | searchCollectionsが未指定の場合、全コレクションのキー一覧を使用 | searchCollections引数がnull/undefined時 |
| BR-33-03 | 統合プロバイダ優先 | 統合検索プロバイダが設定されている場合、バックエンドの検索より優先して使用 | selectIntegrationがtruthyを返す場合 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| searchEntries | Reduxストア (search) | UPDATE | 検索状態（isFetching, term, collections, page）と検索結果（entries）を更新 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SEARCH_ENTRIES_FAILURE | 検索エラー | バックエンドまたは統合プロバイダの検索が失敗した場合 | エラーオブジェクトをペイロードに格納しReduxストアに通知 |

### リトライ仕様

自動リトライ機構はない。ユーザーが再度検索を実行する必要がある。

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

トランザクション管理なし（読み取り専用処理）

## パフォーマンス要件

- 重複検索の検出により不要なAPI呼び出しを防止
- 統合プロバイダ使用時はページネーション対応

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

- バックエンドAPIへのアクセスには認証トークンが必要
- 検索語にXSS攻撃用の文字列が含まれる可能性があるが、React側でのレンダリング時にエスケープされる

## 備考

- clearSearch()アクションで検索状態をクリアできる
- SearchAction型として全アクションのユニオン型がエクスポートされている

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | search.ts | `packages/decap-cms-core/src/actions/search.ts` | アクション定数（16-25行目）: 8種類のアクションタイプ定義。SearchResponse型（65-68行目）: エントリ配列とpaginationを含むレスポンス。SearchAction型（212-221行目）: 全アクションのユニオン型 |

**読解のコツ**: Redux Thunkパターンを使用。`as const`アサーションによるリテラル型の活用に注意。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | search.ts | `packages/decap-cms-core/src/actions/search.ts` | searchEntries関数（109-154行目）が主要なエントリーポイント |

**主要処理フロー**:
1. **109行目**: searchEntries関数定義。searchTerm, searchCollections, page=0を受け取る
2. **114行目**: searchCollectionsが未指定時は全コレクションのキー一覧を使用
3. **121-129行目**: 重複検索チェック。isFetching && 同一条件の場合はreturn
4. **131行目**: searchingEntries（SEARCH_ENTRIES_REQUEST）をdispatch
5. **133-145行目**: 統合プロバイダまたはバックエンドで検索実行
6. **147-153行目**: 結果をsearchSuccess/searchFailureでdispatch

#### Step 3: シンプルアクションクリエイタ

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | search.ts | `packages/decap-cms-core/src/actions/search.ts` | 各アクションクリエイタ（31-102行目）。searchingEntries, searchSuccess, searchFailure, clearSearch等 |

**主要処理フロー**:
- **31-36行目**: searchingEntries - REQUEST アクション生成
- **38-46行目**: searchSuccess - SUCCESS アクション生成（entries, page）
- **48-53行目**: searchFailure - FAILURE アクション生成
- **96-98行目**: clearSearch - 検索状態クリアアクション

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

```
UI (Header / CollectionSearch)
    │
    ├─ dispatch(searchEntries(searchTerm, searchCollections, page))
    │      ├─ 重複検索チェック
    │      ├─ dispatch(searchingEntries(...))
    │      ├─ selectIntegration(state, collection, 'search')
    │      │      ├─ [統合あり] getIntegrationProvider().search()
    │      │      └─ [統合なし] backend.search(collections, searchTerm)
    │      ├─ dispatch(searchSuccess(entries, pagination))
    │      └─ dispatch(searchFailure(error))
    │
    └─ dispatch(clearSearch())
```

### データフロー図

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

ユーザー検索入力       ─▶ searchEntries()              ─▶ Reduxストア更新
  searchTerm              ├─ 重複チェック                   search.isFetching
  searchCollections       ├─ プロバイダ選択                 search.term
  page                    │   ├─ integration.search()      search.entries
                          │   └─ backend.search()          search.page
                          └─ 結果dispatch
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| search.ts | `packages/decap-cms-core/src/actions/search.ts` | ソース | 検索アクションクリエイタの定義 |
| search.spec.js | `packages/decap-cms-core/src/actions/__tests__/search.spec.js` | テスト | searchEntriesのテスト（統合/バックエンド/重複検索） |
| reducers/search.ts | `packages/decap-cms-core/src/reducers/search.ts` | ソース | 検索状態のReducer |
| integrations/index.ts | `packages/decap-cms-core/src/integrations/index.ts` | ソース | 統合プロバイダの管理 |
| backend.ts | `packages/decap-cms-core/src/backend.ts` | ソース | バックエンドのsearchメソッド |
