# 機能設計書 88-インデックス検索

## 概要

本ドキュメントは、Medusaコマースプラットフォームにおけるインデックス検索機能の設計について記述する。インデックスモジュールの検索機能として、同期されたインデックスデータを使用した高速検索を行う。

### 本機能の処理概要

**業務上の目的・背景**：大規模ECサイトでは、数万件以上の商品や注文データから必要な情報を素早く検索することが求められる。インデックス検索機能は、事前に同期されたインデックスデータを使用することで、元テーブルに直接クエリするよりも高速な検索を実現する。ユーザー体験の向上、管理業務の効率化を支援する。

**機能の利用シーン**：商品一覧画面での商品検索、注文一覧画面での注文検索、顧客一覧画面での顧客検索など、全文検索やフィルタリングが必要な場面で利用される。

**主要な処理内容**：
1. インデックス検索（query）：エンティティ名、フィルタ条件、ソート、ページネーションを指定して検索
2. 結果セット取得：検索条件に一致するエンティティデータを返却
3. 集計機能：検索結果の件数、集計値を取得

**関連システム・外部連携**：データ同期機能（インデックスデータの供給）、ストレージプロバイダー（検索実行）と連携する。

**権限による制御**：検索対象エンティティごとにRBACポリシーによるアクセス制御が適用される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | 商品一覧画面 | 補助機能 | 商品の高速検索 |
| 41 | 注文一覧画面 | 補助機能 | 注文の高速検索 |
| 78 | 顧客一覧画面 | 補助機能 | 顧客の高速検索 |

## 機能種別

検索処理 / データ取得

## 入力仕様

### 入力パラメータ

#### インデックス検索（query）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| entity | string | Yes | 検索対象エンティティ名 | インデックス定義に存在 |
| fields | string[] | No | 取得フィールド一覧 | - |
| filters | object | No | フィルタ条件 | - |
| order | object | No | ソート条件 | - |
| skip | number | No | スキップ件数 | 0以上 |
| take | number | No | 取得件数 | 1以上 |

#### filters オブジェクト

| パラメータ名 | 型 | 説明 |
|-------------|-----|------|
| field_name | any | フィールド値の完全一致 |
| field_name.$eq | any | 等価 |
| field_name.$ne | any | 不等価 |
| field_name.$lt | any | 未満 |
| field_name.$lte | any | 以下 |
| field_name.$gt | any | 超過 |
| field_name.$gte | any | 以上 |
| field_name.$like | string | 部分一致（LIKE） |
| field_name.$in | any[] | 含む |
| field_name.$nin | any[] | 含まない |
| $and | object[] | AND条件 |
| $or | object[] | OR条件 |

### 入力データソース

API経由でのJSON形式リクエスト、管理画面からの検索操作

## 出力仕様

### 出力データ

#### QueryResultSet

| 項目名 | 型 | 説明 |
|--------|-----|------|
| data | object[] | 検索結果データ配列 |
| metadata | object | メタデータ |
| .count | number | 検索結果件数 |
| .skip | number | スキップ件数 |
| .take | number | 取得件数 |

### 出力先

APIレスポンス（JSON形式）

## 処理フロー

### 処理シーケンス

```
1. 検索リクエスト受信
   └─ クエリ条件のバリデーション

2. ストレージプロバイダーに委譲
   └─ storageProvider_.query()を呼び出し

3. クエリ構築
   └─ フィルタ条件をSQLに変換
   └─ ソート条件を適用
   └─ ページネーションを適用

4. クエリ実行
   └─ インデックステーブルに対してSELECT実行

5. 結果返却
   └─ データをシリアライズして返却
```

### フローチャート

```mermaid
flowchart TD
    A[検索リクエスト] --> B[バリデーション]
    B --> C[storageProvider_.query]
    C --> D[クエリビルダー]
    D --> E[フィルタ条件変換]
    E --> F[ソート条件適用]
    F --> G[ページネーション適用]
    G --> H[SQL実行]
    H --> I[結果シリアライズ]
    I --> J[QueryResultSet返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-88-1 | エンティティ存在確認 | インデックス定義に存在するエンティティのみ検索可能 | 検索実行時 |
| BR-88-2 | 古いデータ除外 | staled_at IS NULLのデータのみ検索対象 | 検索実行時 |
| BR-88-3 | デフォルトソート | ソート未指定時はcreated_at DESC | 検索実行時 |
| BR-88-4 | ページネーション上限 | takeは最大1000件 | 検索実行時 |

### 計算ロジック

フィルタ条件のSQL変換：
- `$eq` → `= value`
- `$ne` → `!= value`
- `$lt` → `< value`
- `$like` → `LIKE '%value%'`
- `$and` → `(condition1 AND condition2)`
- `$or` → `(condition1 OR condition2)`

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| query | index_data, index_relation | SELECT | インデックス検索 |

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

#### index_data

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | name = entity_name AND staled_at IS NULL | エンティティ名でフィルタ |
| SELECT | data | JSON内のフィールドを取得 | JSONB演算子使用 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NOT_FOUND | 検索エラー | 存在しないエンティティを指定 | 有効なエンティティを指定 |
| INVALID_DATA | 検証エラー | 無効なフィルタ条件 | フィルタ形式を確認 |
| QUERY_ERROR | クエリエラー | SQL実行エラー | クエリ条件を確認 |

### リトライ仕様

データベース接続エラー時は接続プールによる自動リトライが行われる。

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

- 検索はREAD操作のためトランザクション不要
- 複数クエリを並列実行する場合は各クエリが独立

## パフォーマンス要件

- 単純検索：100件取得で100ms以内
- 複雑フィルタ検索：100件取得で500ms以内
- 全文検索：1000件から100件取得で200ms以内
- インデックス使用による検索高速化

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

- 検索対象エンティティごとにアクセス制御を適用
- SQLインジェクション対策（パラメータバインド）
- 機密フィールドの検索結果からの除外

## 備考

- ストレージプロバイダーはPostgresProviderがデフォルト
- 検索対象はGraphQLスキーマで定義されたエンティティに限定
- JSONBフィールドに対する高速検索はGINインデックスを使用

---

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

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

### 推奨読解順序

#### Step 1: 検索インターフェースを理解する

queryメソッドのインターフェース定義を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index-module-service.ts | `packages/modules/index/src/services/index-module-service.ts` | queryメソッド |

**読解のコツ**: queryメソッドはストレージプロバイダーに委譲するシンプルな構造。実際の検索ロジックはストレージプロバイダー内にある。

#### Step 2: 検索メソッドの実装を理解する

IndexModuleServiceのqueryメソッド。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index-module-service.ts | `packages/modules/index/src/services/index-module-service.ts` | queryメソッド |

**主要処理フロー**:
- **189-193行目**: `query`メソッド
  - **192行目**: `storageProvider_.query(config)`に委譲
  - 型パラメータ`TEntry`で戻り値型を推論

#### Step 3: ストレージプロバイダーの実装を理解する

PostgresProviderの検索実装。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | postgres-provider.ts | `packages/modules/index/src/services/postgres-provider.ts` | queryメソッドの実装（存在する場合） |

**読解のコツ**: ストレージプロバイダーはプラガブルな設計。PostgresProviderがデフォルト実装で、index_dataテーブルに対するクエリを生成する。

#### Step 4: クエリビルダーを理解する

フィルタ条件のSQL変換ロジック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | query-builder.ts | `packages/modules/index/src/utils/query-builder.ts` | フィルタ条件変換 |

**読解のコツ**: $eq, $ne, $like, $and, $orなどの演算子をSQLに変換する。JSONBフィールドへのアクセスには`->`演算子を使用。

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

```
API Route / 管理画面
    │
    └─ IndexModuleService.query()
           │
           └─ storageProvider_.query()
                  │
                  ├─▶ クエリビルダー
                  │      ├─▶ フィルタ条件変換
                  │      ├─▶ ソート条件適用
                  │      └─▶ ページネーション適用
                  │
                  └─▶ SQL実行（index_data）
                         │
                         └─▶ 結果シリアライズ
```

### データフロー図

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

検索条件 ───▶ IndexModuleService.query() ───▶ QueryResultSet
     │                  │
     ├─ entity          └─▶ storageProvider_.query()
     ├─ fields                      │
     ├─ filters                     ├─▶ クエリビルダー
     ├─ order                       │
     ├─ skip                        ├─▶ index_data SELECT
     └─ take                        │
                                    └─▶ { data, metadata }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index-module-service.ts | `packages/modules/index/src/services/index-module-service.ts` | サービス | 検索API提供 |
| postgres-provider.ts | `packages/modules/index/src/services/postgres-provider.ts` | プロバイダー | Postgres検索実装 |
| query-builder.ts | `packages/modules/index/src/utils/query-builder.ts` | ユーティリティ | クエリ構築 |
| index-data.ts | `packages/modules/index/src/models/index-data.ts` | モデル | インデックスデータ |
| index.ts | `packages/modules/index/src/index.ts` | エクスポート | モジュールエクスポート |
