# 機能設計書 80-Mustacheテンプレート

## 概要

本ドキュメントは、OpenSearchのMustacheテンプレートモジュール（lang-mustache）の機能設計について記述する。Mustacheテンプレートエンジンによる検索テンプレート機能を提供し、パラメータ化された検索クエリの定義・実行を可能にするモジュールである。

### 本機能の処理概要

Mustacheモジュールは、Mustacheテンプレート言語を使用して検索クエリをテンプレート化し、パラメータを動的に埋め込んで検索を実行する機能を提供する。Search Template API、Multi Search Template API、Render Search Template APIの3つのアクションを実装する。

**業務上の目的・背景**：複雑な検索クエリをテンプレート化して再利用可能にすることで、クライアントアプリケーションからの検索リクエストを簡素化し、クエリロジックの一元管理を実現する。テンプレートはストアドスクリプトとして保存でき、パラメータのみを渡して検索を実行できる。

**機能の利用シーン**：
- 検索テンプレートの定義・実行（Search Template API）
- 複数の検索テンプレートの一括実行（Multi Search Template API）
- テンプレートのレンダリング結果確認（Render Search Template API）
- OpenSearch Dashboardsからの検索テンプレート利用

**主要な処理内容**：
1. MustacheScriptEngine: Mustacheテンプレートのコンパイルと実行
2. SearchTemplateAction: テンプレートベースの検索実行
3. MultiSearchTemplateAction: 複数テンプレートの一括検索実行
4. RenderSearchTemplateAction: テンプレートのレンダリング（検索実行なし）
5. CustomMustacheFactory: JSON/URLエンコーディング対応のMustacheファクトリ

**関連システム・外部連携**：Mustache.java（テンプレートエンジン）、OpenSearch Script Service、Search API。

**権限による制御**：スクリプトの実行はScriptServiceを通じて制御される。ストアドスクリプトの管理にはクラスタ管理権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | 検索テンプレート | 主機能 | Mustache言語で事前レンダリングされた検索定義を使用する処理 |
| 27 | 複数検索テンプレート | 主機能 | 1リクエストで複数の検索テンプレートを実行する処理 |
| 28 | 検索テンプレートレンダリング | 主機能 | Mustache言語で検索定義を事前レンダリングする処理 |
| 143 | スクリプト言語一覧 | 補助機能 | Mustacheテンプレート言語の情報提供 |

## 機能種別

テンプレートエンジン / 検索クエリ生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| source/id | String | Yes | テンプレートソースまたはストアドスクリプトID | Mustache構文 |
| params | Map<String, Object> | No | テンプレートパラメータ | 任意のキー値マップ |
| explain | Boolean | No | スコア計算根拠の表示 | true / false |
| profile | Boolean | No | プロファイル情報の表示 | true / false |
| simulate | Boolean | No | レンダリングのみ（検索実行しない） | true / false |

### 入力データソース

REST APIリクエストボディ。テンプレートはインラインまたはストアドスクリプトとして指定。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| source | BytesReference | レンダリング済みの検索クエリJSON |
| response | SearchResponse | 検索実行結果（simulate=false時） |

### 出力先

REST APIレスポンス。

## 処理フロー

### 処理シーケンス

```
1. REST APIリクエスト受信
   └─ RestSearchTemplateAction / RestMultiSearchTemplateAction / RestRenderSearchTemplateAction
2. テンプレートのコンパイル
   └─ ScriptService.compile()でMustacheScriptEngineを呼び出し
3. Mustacheテンプレートのコンパイル
   └─ MustacheScriptEngine.compile()でMustacheオブジェクトを生成
4. テンプレートのレンダリング
   └─ MustacheExecutableScript.execute()でパラメータを埋め込み、JSONテキストを生成
5. 検索リクエストへの変換
   └─ TransportSearchTemplateAction.convert()でレンダリング結果をSearchSourceBuilderにパース
6. 検索実行
   └─ client.search()でSearchAPIを呼び出し（simulate=false時）
```

### フローチャート

```mermaid
flowchart TD
    A[REST APIリクエスト] --> B{アクション種別}
    B -->|SearchTemplate| C[TransportSearchTemplateAction]
    B -->|MultiSearchTemplate| D[TransportMultiSearchTemplateAction]
    B -->|RenderSearchTemplate| E[TransportRenderSearchTemplateAction]
    C --> F[ScriptService.compile]
    D --> F
    E --> F
    F --> G[MustacheScriptEngine.compile]
    G --> H[MustacheExecutableScript.execute]
    H --> I[テンプレートレンダリング]
    I --> J{simulate?}
    J -->|Yes| K[レンダリング結果のみ返却]
    J -->|No| L[SearchSourceBuilder.parseXContent]
    L --> M[client.search]
    M --> N[SearchResponse返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-80-01 | テンプレートコンテキスト制限 | MustacheScriptEngineはTemplateScript.CONTEXTのみサポート | MustacheScriptEngine compile()（80-82行目） |
| BR-80-02 | シミュレーションモード | simulate=true時は検索を実行せずレンダリング結果のみ返却 | TransportSearchTemplateAction（153-155行目） |
| BR-80-03 | ストアドスクリプト | ScriptType.STORED時はテンプレート言語をnullに設定 | TransportSearchTemplateAction（144行目） |
| BR-80-04 | コンテンツタイプ | content_typeオプションでJSON/YAML等のエスケープ方式を切替 | MustacheScriptEngine createMustacheFactory()（100-105行目） |
| BR-80-05 | trackTotalHitsAsInt互換 | rest_total_hits_as_intパラメータとtemplateのtrack_total_hitsの整合性チェック | TransportSearchTemplateAction checkRestTotalHitsAsInt()（171-192行目） |

### 計算ロジック

テンプレートレンダリングはMustache.execute()でパラメータマップをテンプレートに適用し、StringWriterに出力する。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 検索テンプレート実行 | Luceneインデックス | SELECT | レンダリングされた検索クエリによるインデックス検索 |

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

Mustacheモジュール自体は直接的なデータベース操作を行わない。検索はSearch APIに委譲される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IllegalArgumentException | コンテキストエラー | TemplateScript以外のコンテキストで使用 | TemplateScriptコンテキストで使用 |
| ScriptException | コンパイルエラー | MustacheExceptionが発生（テンプレート構文エラー） | テンプレート構文を修正 |
| GeneralScriptException | ランタイムエラー | テンプレート実行時エラー | テンプレートとパラメータを確認 |
| IllegalArgumentException | 設定エラー | rest_total_hits_as_intとtrack_total_hitsの不整合 | パラメータの組み合わせを修正 |

### リトライ仕様

リトライは不要。テンプレートエラーはリクエスト修正が必要。

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

テンプレートレンダリングと検索はステートレス処理であり、トランザクション管理は不要。

## パフォーマンス要件

Mustacheテンプレートのコンパイル結果はScriptServiceのキャッシュに保持される。テンプレートレンダリング自体は文字列置換処理であり高速。

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

- テンプレート実行はAccessController.doPrivileged()内で行われる（MustacheScriptEngine 136行目）
- SpecialPermission.check()によるセキュリティチェック
- ストアドスクリプトの管理権限制御はScriptServiceに委ねる

## 備考

MustacheModulePluginはScriptPlugin, ActionPlugin, SearchPluginの3つのプラグインインターフェースを実装する。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MustacheModulePlugin.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/MustacheModulePlugin.java` | モジュールエントリーポイント。ScriptEngine, 3つのAction, 3つのRestHandlerを登録 |
| 1-2 | SearchTemplateRequest.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/SearchTemplateRequest.java` | 検索テンプレートリクエストのデータ構造 |
| 1-3 | SearchTemplateResponse.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/SearchTemplateResponse.java` | 検索テンプレートレスポンスのデータ構造 |

**読解のコツ**: MustacheModulePluginが登録する3つのAction（SearchTemplate, MultiSearchTemplate, RenderSearchTemplate）の違いを先に把握すること。

#### Step 2: スクリプトエンジンを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MustacheScriptEngine.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/MustacheScriptEngine.java` | NAME="mustache"。compile()がテンプレートのコンパイル、MustacheExecutableScriptがテンプレート実行 |

**主要処理フロー**:
- **69行目**: NAME = "mustache"
- **79-93行目**: compile() - テンプレート文字列をMustacheオブジェクトにコンパイル。TemplateScript.Factoryとして返却
- **96-98行目**: getSupportedContexts() - TemplateScript.CONTEXTのみサポート
- **100-105行目**: createMustacheFactory() - content_typeオプションに応じたCustomMustacheFactoryの生成
- **115-143行目**: MustacheExecutableScript - execute()でTemplate.execute(writer, params)を呼び出し

#### Step 3: テンプレート検索アクションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TransportSearchTemplateAction.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/TransportSearchTemplateAction.java` | 検索テンプレートの実行。convert()がコアロジック |

**主要処理フロー**:
- **107-134行目**: doExecute() - テンプレートのレンダリング→検索実行→レスポンス返却
- **136-169行目**: convert() - テンプレートのレンダリングとSearchRequestへの変換
  - **142-147行目**: Script生成（テンプレートソースとパラメータ）
  - **148行目**: ScriptService.compile()→TemplateScript.newInstance()でテンプレートコンパイル
  - **149行目**: compiledScript.execute()でレンダリング
  - **153-155行目**: simulate=true時はnullを返却（検索実行しない）
  - **157-168行目**: レンダリング結果をSearchSourceBuilderにパース

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

```
MustacheModulePlugin (モジュール登録)
    |
    +-- getScriptEngine() -> MustacheScriptEngine
    |       +-- compile() -> Mustache (テンプレートコンパイル)
    |       +-- MustacheExecutableScript.execute() -> レンダリング結果
    |
    +-- getActions()
    |       +-- SearchTemplateAction -> TransportSearchTemplateAction
    |       |       +-- convert() -> SearchRequest
    |       |       +-- client.search() -> SearchResponse
    |       |
    |       +-- RenderSearchTemplateAction -> TransportRenderSearchTemplateAction
    |       |       +-- convert() -> レンダリング結果のみ（simulate=true）
    |       |
    |       +-- MultiSearchTemplateAction -> TransportMultiSearchTemplateAction
    |               +-- convert()を複数回実行
    |
    +-- getRestHandlers()
            +-- RestSearchTemplateAction
            +-- RestMultiSearchTemplateAction
            +-- RestRenderSearchTemplateAction
```

### データフロー図

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

テンプレートソース ───> MustacheScriptEngine.compile() ───> Mustache Template
  + パラメータ                                                    |
                                                                  ↓
                                           MustacheExecutableScript.execute()
                                                                  |
                                                                  ↓
                                                        レンダリング済みJSON
                                                                  |
                                           ┌──────────────────────┴───────────────┐
                                           ↓                                      ↓
                                    simulate=true                          simulate=false
                                    レスポンス返却                    SearchSourceBuilder.parse()
                                                                              |
                                                                              ↓
                                                                       client.search()
                                                                              |
                                                                              ↓
                                                                     SearchResponse返却
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MustacheModulePlugin.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/MustacheModulePlugin.java` | ソース | モジュールエントリーポイント |
| MustacheScriptEngine.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/MustacheScriptEngine.java` | ソース | Mustacheスクリプトエンジン |
| CustomMustacheFactory.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/CustomMustacheFactory.java` | ソース | カスタムMustacheファクトリ |
| CustomReflectionObjectHandler.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/CustomReflectionObjectHandler.java` | ソース | カスタムリフレクションハンドラ |
| TransportSearchTemplateAction.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/TransportSearchTemplateAction.java` | ソース | 検索テンプレートアクション |
| TransportMultiSearchTemplateAction.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/TransportMultiSearchTemplateAction.java` | ソース | 複数検索テンプレートアクション |
| TransportRenderSearchTemplateAction.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/TransportRenderSearchTemplateAction.java` | ソース | レンダリングアクション |
| SearchTemplateRequest.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/SearchTemplateRequest.java` | ソース | リクエストデータ構造 |
| SearchTemplateResponse.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/SearchTemplateResponse.java` | ソース | レスポンスデータ構造 |
| RestSearchTemplateAction.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/RestSearchTemplateAction.java` | ソース | RESTハンドラ |
| RestMultiSearchTemplateAction.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/RestMultiSearchTemplateAction.java` | ソース | 複数検索RESTハンドラ |
| RestRenderSearchTemplateAction.java | `modules/lang-mustache/src/main/java/org/opensearch/script/mustache/RestRenderSearchTemplateAction.java` | ソース | レンダリングRESTハンドラ |
