# 画面設計書 61-検索設定

## 概要

本ドキュメントは、Shopware 6 管理画面（Administration）における検索設定画面の設計を記述したものです。商品検索機能の動作をカスタマイズするための管理者向け設定画面です。

### 本画面の処理概要

検索設定画面は、Shopwareストアフロントにおける商品検索機能の挙動を細かく制御するための管理画面です。検索エンジンの設定を最適化することで、顧客がより的確に商品を見つけられるようになります。

**業務上の目的・背景**：ECサイトにおいて検索機能は商品発見の重要な手段です。検索結果の精度が低いと、顧客が目的の商品を見つけられず離脱の原因となります。本画面では、検索対象フィールドの優先度設定、検索条件の論理演算方式、除外キーワードの管理、検索インデックスの再構築などを行うことで、検索品質を向上させることができます。

**画面へのアクセス方法**：管理画面にログイン後、左メニューの「設定」 > 「一般」セクション > 「検索」をクリックしてアクセスします。URL パスは `#/sw/settings/search/index/general` です。

**主要な操作・処理内容**：
1. **検索動作設定**：AND/OR検索条件の切り替え、最小検索文字数の設定
2. **検索可能コンテンツの設定**：商品名、商品番号、EAN、メーカー名などの検索対象フィールドとその優先度（ランキングポイント）を設定
3. **カスタムフィールドの検索設定**：カスタムフィールドを検索対象に含めるかどうかの設定
4. **除外キーワードの管理**：「the」「a」「and」などの検索から除外するキーワードの追加・削除
5. **検索インデックスの再構築**：商品検索キーワードインデックスの再構築実行
6. **ライブ検索テスト**：設定した内容で実際に検索をテストする機能

**画面遷移**：
- 遷移元：設定一覧画面（sw-settings-index）
- 遷移先：なし（設定画面のため）
- 内部タブ：「一般」タブと「ライブ検索」タブ間を遷移可能

**権限による表示制御**：
- `product_search_config.viewer`：閲覧のみ可能
- `product_search_config.editor`：設定の編集が可能
- `product_search_config.creator`：新規設定の作成が可能
- `product_search_config.deleter`：設定の削除が可能

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 32 | 商品検索 | 補助機能 | 商品検索の優先度・設定を管理 |

## 画面種別

設定

## URL/ルーティング

| 項目 | 値 |
|------|---|
| モジュール名 | sw-settings-search |
| メインルート | sw.settings.search.index |
| 一般タブルート | sw.settings.search.index.general |
| ライブ検索タブルート | sw.settings.search.index.liveSearch |
| URLパス | #/sw/settings/search/index/general |

## 入出力項目

### 検索動作設定（Search Behaviour）

| 項目名 | 項目ID | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| 検索条件 | andLogic | Boolean | Yes | AND検索（true）またはOR検索（false）の切り替え |
| 最小検索文字数 | minSearchLength | Integer | Yes | 検索を実行する最小文字数（1〜20） |

### 検索可能コンテンツ設定（Searchable Content）

| 項目名 | 項目ID | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| フィールド名 | field | String | Yes | 検索対象のフィールド名 |
| 検索可能 | searchable | Boolean | No | 検索対象とするかどうか |
| ランキングポイント | ranking | Integer | No | 検索結果の優先度（0〜1000） |
| キーワード分割 | tokenize | Boolean | No | キーワードを分割して検索するか |

### 除外キーワード設定（Excluded Search Terms）

| 項目名 | 項目ID | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| 除外キーワード | excludedTerms | Array<String> | No | 検索から除外するキーワードリスト |

## 表示項目

### 一般タブ

| セクション | 表示項目 | 説明 |
|------------|----------|------|
| 検索動作 | 検索条件選択 | AND/OR検索の選択ラジオボタン |
| 検索動作 | 最小検索文字数 | 数値入力フィールド（1〜20） |
| 検索可能コンテンツ | フィールド一覧 | 検索対象フィールドのデータグリッド |
| 検索可能コンテンツ | 一般フィールドタブ | 標準フィールドの設定 |
| 検索可能コンテンツ | カスタムフィールドタブ | カスタムフィールドの設定 |
| 除外キーワード | キーワード一覧 | 除外キーワードのデータグリッド |
| 検索インデックス | 再構築ボタン | インデックス再構築の実行ボタン |
| 検索インデックス | 最終インデックス日時 | 最後にインデックスが構築された日時 |
| 検索インデックス | 進捗バー | 再構築中の進捗表示 |

### ライブ検索タブ

| セクション | 表示項目 | 説明 |
|------------|----------|------|
| 販売チャネル選択 | ドロップダウン | テスト対象の販売チャネル選択 |
| 検索入力 | テキストフィールド | テスト検索キーワード入力 |
| 検索結果 | 商品一覧 | 検索結果の商品リスト |
| 検索結果 | キーワードハイライト | マッチしたキーワードの強調表示 |

## イベント仕様

### 1-保存ボタン押下

**トリガー**: 「保存」ボタンクリックまたはショートカット（Ctrl/Cmd + S）

**処理フロー**:
1. `onSaveSearchSettings` メソッドが実行される
2. `productSearchRepository.save()` で設定をAPIに送信
3. 成功時: 成功通知を表示、設定を再読み込み
4. 失敗時: エラー通知を表示

**データフロー**:
```
ユーザー入力 → productSearchConfigs → Repository.save() → API → Database
```

### 2-検索条件変更（AND/OR切り替え）

**トリガー**: 検索条件のラジオボタン変更

**処理フロー**:
1. `searchBehaviourConfigs.andLogic` の値が更新される
2. 画面は編集中状態になる
3. 保存ボタン押下で永続化

### 3-検索可能コンテンツのインライン編集

**トリガー**: データグリッドのセルをダブルクリック

**処理フロー**:
1. インライン編集モードが有効化
2. 値を変更
3. 編集完了時に `saveConfig()` が呼び出される
4. `productSearchFieldRepository.saveAll()` で一括保存

### 4-除外キーワード追加

**トリガー**: 「キーワード追加」ボタンクリック

**処理フロー**:
1. `onInsertTerm()` が実行される
2. 新しい空行がグリッドに追加される
3. インライン編集モードが自動的に有効化
4. 値入力後、`onSaveEdit()` で保存

### 5-検索インデックス再構築

**トリガー**: 「インデックス再構築」ボタンクリック

**処理フロー**:
1. `rebuildSearchIndex()` が実行される
2. `productIndexService.index()` APIを呼び出し
3. ポーリングで進捗を監視（3秒間隔）
4. 完了まで繰り返し、進捗バーを更新
5. 完了時に成功通知を表示

### 6-デフォルトにリセット

**トリガー**: 「デフォルトにリセット」ボタンクリック

**処理フロー**:
1. `onResetToDefault()` または `onResetExcludedSearchTermDefault()` が実行される
2. 各フィールドをデフォルト値に復元
3. 設定を保存

### 7-言語切り替え

**トリガー**: 言語スイッチャーで言語変更

**処理フロー**:
1. `onChangeLanguage()` が実行される
2. 選択された言語に対応する検索設定を取得
3. 画面を再描画

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 検索動作設定保存 | product_search_config | UPDATE | andLogic, minSearchLength を更新 |
| 検索可能コンテンツ保存 | product_search_config_field | UPDATE | searchable, ranking, tokenize を更新 |
| 検索可能コンテンツ追加 | product_search_config_field | INSERT | 新しいフィールド設定を追加 |
| 検索可能コンテンツ削除 | product_search_config_field | DELETE | フィールド設定を削除 |
| 除外キーワード更新 | product_search_config | UPDATE | excludedTerms 配列を更新 |
| インデックス再構築 | product_search_keyword | DELETE/INSERT | キーワードインデックスを再構築 |

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

#### product_search_config

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | and_logic | true/false | AND検索/OR検索の設定 |
| UPDATE | min_search_length | 1〜20の整数 | 最小検索文字数 |
| UPDATE | excluded_terms | JSON配列 | 除外キーワードリスト |
| SELECT | language_id | Context.api.languageId | 言語IDでフィルタ |

#### product_search_config_field

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | searchable | true/false | 検索対象フラグ |
| UPDATE | ranking | 0〜1000の整数 | 検索優先度 |
| UPDATE | tokenize | true/false | キーワード分割フラグ |
| INSERT | field | フィールド名文字列 | 検索対象フィールド |
| INSERT | search_config_id | UUID | 親設定のID |

#### product_search_keyword

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE/INSERT | keyword | 商品から抽出 | インデックス再構築時 |
| SELECT | created_at | MAX集計 | 最終インデックス日時取得 |

## メッセージ仕様

| 種別 | メッセージキー | メッセージ内容 | 表示条件 |
|------|--------------|--------------|---------|
| 成功 | sw-settings-search.notification.saveSuccess | 設定が保存されました | 保存成功時 |
| エラー | sw-settings-search.notification.saveError | 設定の保存に失敗しました | 保存失敗時 |
| エラー | sw-settings-search.notification.loadError | 設定の読み込みに失敗しました | 読み込み失敗時 |
| 成功 | sw-settings-search.notification.index.success | インデックスの再構築が完了しました | インデックス再構築完了時 |
| 情報 | sw-settings-search.notification.index.started | インデックスの再構築を開始しました | インデックス再構築開始時 |
| 成功 | sw-settings-search.notification.createExcludedTermSuccess | 除外キーワードを追加しました | 除外キーワード追加成功時 |
| 成功 | sw-settings-search.notification.updateExcludedTermSuccess | 除外キーワードを更新しました | 除外キーワード更新成功時 |
| 成功 | sw-settings-search.notification.deleteExcludedTermSuccess | 除外キーワードを削除しました | 除外キーワード削除成功時 |
| エラー | sw-settings-search.notification.excludedTermRequired | 除外キーワードは必須です | 空のキーワード保存時 |
| エラー | sw-settings-search.notification.excludedTermAlreadyExists | 除外キーワードは既に存在します | 重複キーワード追加時 |
| 成功 | sw-settings-search.notification.resetToDefaultExcludedTermSuccess | デフォルトにリセットしました | デフォルトリセット成功時 |
| 確認 | sw-settings-search.textLeaveConfirm | 保存されていない変更があります。このページを離れますか？ | 未保存状態でページ離脱時 |

## 例外処理

| 例外状態 | 対応処理 | 画面表示 |
|---------|---------|---------|
| 権限不足 | 編集ボタン無効化 | 保存ボタンが無効化され、ツールチップで権限不足を通知 |
| API通信エラー | エラー通知表示 | 「設定の保存に失敗しました」等のエラーメッセージ |
| 設定未存在 | デフォルト設定作成 | システム言語のデフォルト設定をコピーして新規作成 |
| インデックス再構築中断 | ポーリング停止 | 進捗バーがリセットされ、再開可能な状態に |
| 未保存で画面離脱 | 確認モーダル表示 | 離脱確認ダイアログを表示 |

## 備考

- 検索設定は言語ごとに独立して管理されます
- Elasticsearch が有効な場合、一部の設定は Elasticsearch の設定に影響します
- インデックス再構築は商品数が多い場合、時間がかかる場合があります
- 検索ランキングポイントは相対的な優先度であり、絶対値ではありません

---

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

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

### 推奨読解順序

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

まず、検索設定で使用されるエンティティ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | product_search_config | `src/Core/Content/Product/Aggregate/ProductSearchConfig/ProductSearchConfigDefinition.php` | 検索設定エンティティの定義 |
| 1-2 | product_search_config_field | `src/Core/Content/Product/Aggregate/ProductSearchConfigField/ProductSearchConfigFieldDefinition.php` | 検索フィールド設定の定義 |

**読解のコツ**: Shopware 6 の DAL（Data Abstraction Layer）では、`Definition` クラスでエンティティのフィールドと関連を定義します。

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

処理の起点となるモジュール登録とルーティングを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/index.js` | モジュール登録とルート定義 |

**主要処理フロー**:
1. **49-102行目**: `Module.register` でモジュールを登録
2. **61-93行目**: ルート定義（index、general、liveSearch）
3. **96-101行目**: 設定メニューへの項目追加

#### Step 3: ページコンポーネントを理解する

メインページコンポーネントの構造と状態管理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sw-settings-search/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/page/sw-settings-search/index.js` | ページのメインロジック |
| 3-2 | sw-settings-search.html.twig | `src/Administration/Resources/app/administration/src/module/sw-settings-search/page/sw-settings-search/sw-settings-search.html.twig` | テンプレート構造 |

**主要処理フロー**:
- **30-46行目**: コンポーネントの状態（data）定義
- **94-96行目**: `createdComponent` でデータ初期化
- **124-143行目**: `getProductSearchConfigs` で設定取得
- **214-234行目**: `onSaveSearchSettings` で設定保存

#### Step 4: 検索動作設定コンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sw-settings-search-search-behaviour/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/component/sw-settings-search-search-behaviour/index.js` | AND/OR検索、最小文字数設定 |

**主要処理フロー**:
- **38-50行目**: 検索条件オプション（AND/OR）の定義

#### Step 5: 検索可能コンテンツコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | sw-settings-search-searchable-content/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/component/sw-settings-search-searchable-content/index.js` | フィールド設定のCRUD操作 |

**主要処理フロー**:
- **51-187行目**: フィールド設定のデフォルト値定義
- **335-354行目**: `getProductSearchFieldsList` でフィールド一覧取得
- **356-375行目**: `saveConfig` でフィールド設定保存

#### Step 6: 除外キーワードコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | sw-settings-search-excluded-search-terms/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/component/sw-settings-search-excluded-search-terms/index.js` | 除外キーワードの管理 |

**主要処理フロー**:
- **116-126行目**: `onInsertTerm` で新規キーワード追加
- **204-238行目**: `onSaveEdit` でキーワード保存（バリデーション含む）
- **260-281行目**: `saveConfig` でAPI経由で永続化

#### Step 7: 検索インデックスコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 7-1 | sw-settings-search-search-index/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/component/sw-settings-search-search-index/index.js` | インデックス再構築機能 |
| 7-2 | productIndex.api.service.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/service/productIndex.api.service.js` | インデックスAPI呼び出し |

**主要処理フロー**:
- **162-172行目**: `rebuildSearchIndex` でインデックス再構築開始
- **121-147行目**: `updateProgress` でポーリングによる進捗監視
- **13-16行目（APIサービス）**: `/_action/indexing/product.indexer` エンドポイント呼び出し

#### Step 8: 権限設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 8-1 | acl/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/acl/index.js` | 権限マッピング定義 |

**主要処理フロー**:
- **4-58行目**: viewer/editor/creator/deleter ロールと必要権限の定義

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

```
sw-settings-search (Page)
    │
    ├─ sw-settings-search-view-general (View)
    │      ├─ sw-settings-search-search-behaviour
    │      │      └─ [AND/OR設定、最小文字数]
    │      │
    │      ├─ sw-settings-search-searchable-content
    │      │      ├─ sw-settings-search-searchable-content-general
    │      │      └─ sw-settings-search-searchable-content-customfields
    │      │
    │      ├─ sw-settings-search-excluded-search-terms
    │      │      └─ excludedSearchTermService (API)
    │      │
    │      └─ sw-settings-search-search-index
    │             └─ productIndexService (API)
    │
    └─ sw-settings-search-view-live-search (View)
           └─ sw-settings-search-live-search
                  ├─ sw-settings-search-live-search-keyword
                  └─ livesearch.api.service
```

### データフロー図

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

ユーザー入力              Vue Component                   API/Database
─────────────────────────────────────────────────────────────────────

検索条件設定      ───▶   sw-settings-search-          ───▶  product_search_config
(AND/OR, 文字数)         search-behaviour                   (andLogic, minSearchLength)

フィールド設定    ───▶   sw-settings-search-          ───▶  product_search_config_field
(ranking等)              searchable-content                 (searchable, ranking, tokenize)

除外キーワード    ───▶   sw-settings-search-          ───▶  product_search_config
                         excluded-search-terms              (excludedTerms JSON)

インデックス再構築 ───▶  sw-settings-search-          ───▶  product_search_keyword
                         search-index                       (DELETE/INSERT)
                               │
                               └─▶ productIndexService
                                     └─▶ /_action/indexing/product.indexer
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/index.js` | ソース | モジュール登録・ルート定義 |
| sw-settings-search/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/page/sw-settings-search/index.js` | ソース | ページメインロジック |
| sw-settings-search.html.twig | `src/Administration/Resources/app/administration/src/module/sw-settings-search/page/sw-settings-search/sw-settings-search.html.twig` | テンプレート | ページテンプレート |
| sw-settings-search-view-general/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/view/sw-settings-search-view-general/index.js` | ソース | 一般タブビュー |
| sw-settings-search-view-live-search/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/view/sw-settings-search-view-live-search/index.js` | ソース | ライブ検索タブビュー |
| sw-settings-search-search-behaviour/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/component/sw-settings-search-search-behaviour/index.js` | ソース | 検索動作設定コンポーネント |
| sw-settings-search-searchable-content/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/component/sw-settings-search-searchable-content/index.js` | ソース | 検索可能コンテンツコンポーネント |
| sw-settings-search-excluded-search-terms/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/component/sw-settings-search-excluded-search-terms/index.js` | ソース | 除外キーワードコンポーネント |
| sw-settings-search-search-index/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/component/sw-settings-search-search-index/index.js` | ソース | 検索インデックスコンポーネント |
| productIndex.api.service.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/service/productIndex.api.service.js` | ソース | インデックスAPIサービス |
| livesearch.api.service.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/service/livesearch.api.service.js` | ソース | ライブ検索APIサービス |
| acl/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-search/acl/index.js` | ソース | 権限定義 |
