# 機能設計書 110-パーコレータ

## 概要

本ドキュメントは、OpenSearchのパーコレータ（Percolator）モジュールの設計を記述する。通常の検索（ドキュメントに対してクエリを実行）とは逆に、登録済みのクエリに対してドキュメントを照合するPercolator機能を提供するモジュールである。

### 本機能の処理概要

**業務上の目的・背景**：アラート通知、コンテンツ分類、リアルタイムフィルタリングなど、「あらかじめ登録したクエリ条件に新しいドキュメントがマッチするかを判定する」ユースケースに対応する。通常の検索がドキュメントセットに対してクエリを実行するのに対し、パーコレータはクエリセットに対してドキュメントを実行する逆の処理を行う。

**機能の利用シーン**：ニュース記事のカテゴリ自動分類、セキュリティアラートルールとのマッチング、メール通知のトリガー条件判定、ドキュメント受信時のリアルタイムフィルタリングで利用される。

**主要な処理内容**：
1. PercolatorFieldMapperによるクエリのインデックス保存（percolatorフィールドタイプ）
2. PercolateQueryBuilderによるパーコレーションクエリの構築
3. PercolateQueryによるクエリ実行（MemoryIndexまたはDirectoryReader使用）
4. QueryAnalyzerによるクエリからの検索ターム抽出と候補クエリの効率的な絞り込み
5. PercolatorMatchedSlotSubFetchPhaseによるマッチしたスロット情報の取得
6. PercolatorHighlightSubFetchPhaseによるハイライト情報の取得

**関連システム・外部連携**：Lucene IndexSearcher、MapperPlugin、SearchPlugin。

**権限による制御**：通常のインデックス/検索権限に従う。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | パーコレータは検索APIの一部として動作 |

## 機能種別

検索 / パターンマッチング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| field | String | Yes | パーコレータフィールド名 | 有効なフィールド名 |
| document | Object | Yes（documentまたはdocuments必須） | 照合対象ドキュメント | 有効なJSON |
| documents | Object[] | No | 複数の照合対象ドキュメント | 有効なJSON配列 |
| index | String | No | ドキュメント取得元インデックス | 有効なインデックス名 |
| id | String | No | ドキュメント取得元ID | - |
| routing | String | No | ルーティング値 | - |
| preference | String | No | 検索プリファレンス | - |
| version | Long | No | ドキュメントバージョン | - |
| name | String | No | パーコレーションクエリ名 | - |

### 入力データソース

- 検索リクエストのクエリ部分（PercolateQueryBuilder）
- インライン指定またはインデックスからの既存ドキュメント

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| hits.hits[] | Object[] | マッチしたクエリドキュメント |
| hits.hits[]._id | String | マッチしたクエリのドキュメントID |
| hits.hits[]._score | float | マッチスコア |
| hits.hits[].fields._percolator_document_slot | int[] | マッチしたドキュメントスロット |
| hits.hits[].highlight | Object | ハイライト情報 |

### 出力先

REST APIレスポンス（JSON形式）

## 処理フロー

### 処理シーケンス

```
1. PercolateQueryBuilder.toQuery()
   └─ ドキュメントの解析（インラインまたはインデックスから取得）
2. MemoryIndex/DirectoryReaderの構築
   └─ 照合対象ドキュメントをインメモリインデックスとして構築
3. QueryAnalyzerによる候補クエリの絞り込み
   └─ ドキュメントのタームから候補クエリを効率的に特定
4. PercolateQuery実行
   └─ 候補クエリをドキュメントに対して実行
5. マッチ結果の収集
   └─ PercolatorMatchedSlotSubFetchPhaseでスロット情報収集
   └─ PercolatorHighlightSubFetchPhaseでハイライト生成
```

### フローチャート

```mermaid
flowchart TD
    A[Percolate Request] --> B[PercolateQueryBuilder]
    B --> C{ドキュメントソース?}
    C -->|インライン| D[ドキュメント解析]
    C -->|インデックス| E[GET APIでドキュメント取得]
    D --> F[MemoryIndex構築]
    E --> F
    F --> G[QueryAnalyzer候補絞り込み]
    G --> H[PercolateQuery実行]
    H --> I[マッチ結果収集]
    I --> J[Response返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-1001 | 単一/複数ドキュメント | documentまたはdocumentsのいずれかを指定 | パーコレーションクエリ実行時 |
| BR-1002 | クエリ保存形式 | パーコレータフィールドはクエリをバイナリ形式でインデックスに保存 | ドキュメントインデックス時 |
| BR-1003 | 未マップフィールド | INDEX_MAP_UNMAPPED_FIELDS_AS_TEXT_SETTINGでテキストとして扱う | クエリ解析時 |

### 計算ロジック

QueryAnalyzerがクエリからタームを抽出し、CoveringQueryを使用して候補クエリを効率的に絞り込む。最小タームマッチ数でフィルタリング。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| クエリ登録 | パーコレータインデックス | INSERT | percolatorフィールドにクエリをインデックス |
| パーコレーション | パーコレータインデックス | SELECT | 登録済みクエリの照合実行 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | IllegalArgumentException | documentとdocumentsの両方指定 | いずれか一方を指定 |
| 404 | ResourceNotFoundException | 指定ドキュメントが存在しない | 正しいindex/idを指定 |
| 400 | ParsingException | クエリの解析失敗 | クエリ構文を確認 |

### リトライ仕様

特になし。

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

パーコレーションクエリは読み取り操作。クエリの登録はインデックス操作のトランザクションに従う。

## パフォーマンス要件

- QueryAnalyzerによる候補クエリの事前絞り込みで検索効率を向上
- MemoryIndex使用時は1ドキュメント=インメモリ処理で高速
- DirectoryReader使用時は複数ドキュメントをバッチ処理可能

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

- パーコレータクエリの登録・実行は通常のインデックス/検索権限に従う
- 登録されたクエリにはインデックスデータとして同等のアクセス制御が適用

## 備考

- パーコレータフィールドタイプ: "percolator"
- INDEX_MAP_UNMAPPED_FIELDS_AS_TEXT_SETTING で未定義フィールドのマッピング制御
- PercolateQueryBuilder.NAME がクエリ名として使用される
- BinaryRangeクラスはレンジクエリのバイナリ表現を提供

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | PercolatorFieldMapper.java | `modules/percolator/src/main/java/org/opensearch/percolator/PercolatorFieldMapper.java` | パーコレータフィールドのマッピング定義。クエリの保存形式 |

**読解のコツ**: PercolatorFieldMapperはParametrizedFieldMapperを継承し、クエリをバイナリDocValuesとして保存する。タームの抽出ロジックがインデックス時に実行される点に注目。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | PercolatorModulePlugin.java | `modules/percolator/src/main/java/org/opensearch/percolator/PercolatorModulePlugin.java` | モジュールプラグイン定義 |

**主要処理フロー**:
1. **51-53行目**: `getQueries()`でPercolateQueryBuilderを検索クエリとして登録
2. **56-58行目**: `getFetchSubPhases()`でMatchedSlotSubFetchPhaseとHighlightSubFetchPhaseを登録
3. **61-63行目**: `getSettings()`でINDEX_MAP_UNMAPPED_FIELDS_AS_TEXT_SETTING設定を公開
4. **66-68行目**: `getMappers()`でpercolatorフィールドタイプをマッパー登録

#### Step 3: クエリ実行層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | PercolateQueryBuilder.java | `modules/percolator/src/main/java/org/opensearch/percolator/PercolateQueryBuilder.java` | クエリビルダー。ドキュメントの解析、MemoryIndex/DirectoryReaderの構築 |
| 3-2 | PercolateQuery.java | `modules/percolator/src/main/java/org/opensearch/percolator/PercolateQuery.java` | 実際のパーコレーションクエリ実行 |
| 3-3 | QueryAnalyzer.java | `modules/percolator/src/main/java/org/opensearch/percolator/QueryAnalyzer.java` | クエリのターム分析と候補絞り込み |

#### Step 4: フェッチフェーズを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | PercolatorMatchedSlotSubFetchPhase.java | `modules/percolator/src/main/java/org/opensearch/percolator/PercolatorMatchedSlotSubFetchPhase.java` | マッチスロット情報の取得 |
| 4-2 | PercolatorHighlightSubFetchPhase.java | `modules/percolator/src/main/java/org/opensearch/percolator/PercolatorHighlightSubFetchPhase.java` | ハイライト情報の取得 |

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

```
PercolatorModulePlugin
    |
    +-- PercolateQueryBuilder (SearchPlugin.QuerySpec)
    |       |
    |       +-- toQuery()
    |               +-- MemoryIndex / DirectoryReader構築
    |               +-- PercolateQuery生成
    |                       +-- QueryAnalyzer.analyze()
    |                       +-- CoveringQuery (候補絞り込み)
    |                       +-- Weight.scorer() (マッチ実行)
    |
    +-- PercolatorFieldMapper (MapperPlugin)
    |       +-- parseCreateField() (クエリのインデックス保存)
    |       +-- TypeParser
    |
    +-- PercolatorMatchedSlotSubFetchPhase (FetchSubPhase)
    +-- PercolatorHighlightSubFetchPhase (FetchSubPhase)
```

### データフロー図

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

1. クエリ登録フェーズ:
Query JSON         ----> PercolatorFieldMapper
                          |
                          +-> クエリ解析
                          +-> ターム抽出          -----> Lucene Index
                          +-> バイナリDocValues保存         (percolator field)

2. パーコレーション実行フェーズ:
Document JSON      ----> PercolateQueryBuilder
                          |
                          +-> MemoryIndex構築
                          |
                          v
Percolator Index   ----> QueryAnalyzer
                          |
                          +-> 候補クエリ絞り込み
                          |
                          v
                   PercolateQuery.scorer()
                          |
                          +-> 各候補クエリ実行    -----> マッチ結果
                          +-> MatchedSlot収集     -----> スロット情報
                          +-> Highlight生成       -----> ハイライト情報
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| PercolatorModulePlugin.java | `modules/percolator/src/main/java/org/opensearch/percolator/PercolatorModulePlugin.java` | ソース | モジュールプラグイン |
| PercolatorFieldMapper.java | `modules/percolator/src/main/java/org/opensearch/percolator/PercolatorFieldMapper.java` | ソース | フィールドマッパー |
| PercolateQueryBuilder.java | `modules/percolator/src/main/java/org/opensearch/percolator/PercolateQueryBuilder.java` | ソース | クエリビルダー |
| PercolateQuery.java | `modules/percolator/src/main/java/org/opensearch/percolator/PercolateQuery.java` | ソース | パーコレーションクエリ |
| QueryAnalyzer.java | `modules/percolator/src/main/java/org/opensearch/percolator/QueryAnalyzer.java` | ソース | クエリ分析 |
| PercolatorMatchedSlotSubFetchPhase.java | `modules/percolator/src/main/java/org/opensearch/percolator/PercolatorMatchedSlotSubFetchPhase.java` | ソース | マッチスロット取得 |
| PercolatorHighlightSubFetchPhase.java | `modules/percolator/src/main/java/org/opensearch/percolator/PercolatorHighlightSubFetchPhase.java` | ソース | ハイライト取得 |
| BinaryRange.java | `modules/percolator/src/main/java/org/opensearch/percolator/BinaryRange.java` | ソース | バイナリレンジ表現 |
