# 機能設計書 70-共通アナライザ

## 概要

本ドキュメントは、OpenSearchの共通アナライザモジュール（analysis-common）に関する機能設計書である。本モジュールはStandard、Simple、Whitespace等の標準テキストアナライザ群を提供し、CommonAnalysisModulePluginクラスを中心に多数のアナライザ、トークナイザ、トークンフィルタ、キャラクタフィルタを登録する。

### 本機能の処理概要

**業務上の目的・背景**：全文検索を実現するには、テキストデータを適切にトークン化（分割）し、正規化する必要がある。共通アナライザモジュールは、Luceneが提供する多数のテキスト解析コンポーネントをOpenSearchから利用可能にするための基盤モジュールである。

**機能の利用シーン**：インデックス作成時のフィールドマッピングでアナライザを指定する場合、検索クエリのテキスト解析、_analyze APIでのテキスト解析テスト等に利用される。30以上の言語アナライザ、50以上のトークンフィルタ、10以上のトークナイザを提供する。

**主要な処理内容**：
1. アナライザの登録（fingerprint、pattern、snowball、30以上の言語アナライザ）
2. トークンフィルタの登録（50以上のフィルタ：lowercase、stemmer、stop、ngram等）
3. トークナイザの登録（classic、edge_ngram、keyword、letter、pattern等）
4. キャラクタフィルタの登録（html_strip、mapping、pattern_replace）
5. プリビルトアナライザの登録（standard、simple、stop、whitespace、keyword等）
6. Painlessスクリプトとの連携（AnalysisPredicateScript、ScriptedConditionTokenFilter）

**関連システム・外部連携**：Apache Luceneの解析フレームワーク（org.apache.lucene.analysis）を基盤とする。Painlessスクリプトとの連携によりカスタム条件フィルタをサポート。

**権限による制御**：アナライザの使用はインデックス作成権限で制御される。_analyze APIの使用にはインデックス読取権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 55 | アナライズ | 主機能 | テキストに対して解析プロセスを実行しトークン分解を返す処理 |

## 機能種別

テキスト解析 / プラグインモジュール

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| analyzer | String | No | 使用するアナライザ名 | 登録済みアナライザ名 |
| tokenizer | String | No | 使用するトークナイザ名 | 登録済みトークナイザ名 |
| filter | String[] | No | 使用するトークンフィルタ名のリスト | 登録済みフィルタ名 |
| char_filter | String[] | No | 使用するキャラクタフィルタ名のリスト | 登録済みフィルタ名 |
| text | String/String[] | Yes (_analyze時) | 解析対象テキスト | 空でない文字列 |

### 入力データソース

インデックスマッピング設定、_analyze API（POST /_analyze, POST /{index}/_analyze）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| tokens | Array | トークン化された結果の配列 |
| tokens[].token | String | トークン文字列 |
| tokens[].start_offset | int | 元テキストでの開始オフセット |
| tokens[].end_offset | int | 元テキストでの終了オフセット |
| tokens[].type | String | トークンタイプ |
| tokens[].position | int | トークン位置 |

### 出力先

REST APIレスポンス（_analyze API）、Luceneインデックス（インデックス時）

## 処理フロー

### 処理シーケンス

```
1. テキスト入力
   └─ インデックス時のドキュメントフィールド値、または_analyze APIリクエスト
2. キャラクタフィルタ適用（オプション）
   └─ html_strip、mapping、pattern_replace等
3. トークナイザでテキストをトークン化
   └─ standard、keyword、pattern、whitespace等
4. トークンフィルタの適用（チェーン）
   └─ lowercase、stop、stemmer、ngram等を順次適用
5. 結果の出力
   └─ トークンストリームをLuceneインデックスに書き込み、またはAPI応答
```

### フローチャート

```mermaid
flowchart TD
    A[テキスト入力] --> B[キャラクタフィルタ]
    B --> C[トークナイザ]
    C --> D[トークンフィルタ1]
    D --> E[トークンフィルタ2]
    E --> F[トークンフィルタN]
    F --> G[トークンストリーム出力]
    G --> H{用途}
    H -->|インデックス時| I[Luceneインデックスへ書込]
    H -->|検索時| J[検索クエリのトークン化]
    H -->|_analyze API| K[API応答]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-70-01 | 非推奨名の警告 | edgeNGram/nGram等の非推奨名使用時にdeprecation警告を出力 | フィルタ/トークナイザ指定時 |
| BR-70-02 | バージョン制限 | V3.0.0以降のインデックスでは非推奨名（edgeNGram等）は使用不可 | インデックス作成時 |
| BR-70-03 | 設定必須フィルタ | common_grams、elision、keep等の一部フィルタは分析設定が必須 | フィルタ指定時 |

### 計算ロジック

特になし（テキスト解析はLuceneのAnalyzerフレームワークに委譲）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| アナライズ | なし | - | テキスト解析結果を返すのみ |
| インデックス時 | Luceneインデックス | WRITE | 解析済みトークンの転置インデックス書込 |

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

特になし（テキスト解析はメモリ内で実行される）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IllegalArgumentException | パラメータエラー | V3.0.0以降のインデックスで非推奨トークナイザ名を使用 | 新しい名前（edge_ngram等）を使用 |
| IllegalArgumentException | 設定エラー | 設定必須フィルタに設定が不足 | 必要な設定を追加 |

### リトライ仕様

テキスト解析処理にリトライ仕様はない。

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

テキスト解析はステートレスな処理であり、トランザクション管理は不要。

## パフォーマンス要件

- アナライザはインデックスごとにキャッシュされ、再利用される
- プリビルトアナライザはCachingStrategyに基づいてキャッシュされる
- 軽量なフィルタチェーン構造によるインメモリ処理

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

- ScriptedConditionTokenFilterはPainlessスクリプトを実行するため、スクリプトセキュリティの制約が適用される
- テキスト解析自体にはセキュリティ上のリスクは低い

## 備考

- CommonAnalysisModulePluginはPluginに加えてAnalysisPluginとScriptPluginの2つのインターフェースを実装
- AnalysisPredicateScript.CONTEXTがスクリプトコンテキストとして登録される
- 30以上の言語別アナライザ（Arabic、Armenian、Basque、Bengali、...）を提供
- Snowball Stemmerの統合（DutchStemmer、FrenchStemmer等）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AnalysisPredicateScript.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/AnalysisPredicateScript.java` | スクリプト条件フィルタ用のスクリプトコンテキスト |

**読解のコツ**: CommonAnalysisModulePluginの主要構造は、getAnalyzers()、getTokenFilters()、getTokenizers()、getCharFilters()、getPreBuiltAnalyzerProviderFactories()、getPreConfiguredTokenFilters()、getPreConfiguredTokenizers()、getPreConfiguredCharFilters()の各メソッドである。これらはAnalysisPluginインターフェースのメソッドオーバーライドである。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CommonAnalysisModulePlugin.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/CommonAnalysisModulePlugin.java` | モジュールプラグインの全体構造 |

**主要処理フロー**:
1. **174行目**: クラス宣言、Plugin/AnalysisPlugin/ScriptPluginを実装
2. **198-201行目**: getContexts() - AnalysisPredicateScript.CONTEXTを登録
3. **204-248行目**: getAnalyzers() - fingerprint、pattern、snowball、30以上の言語アナライザを登録
4. **251-319行目以降**: getTokenFilters() - 50以上のトークンフィルタを登録（apostrophe、arabic_normalization、asciifolding等）
5. **275-289行目**: edgeNGram非推奨処理 - V3.0.0以降はIllegalArgumentException

#### Step 3: 個別アナライザプロバイダを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FingerprintAnalyzerProvider.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/FingerprintAnalyzerProvider.java` | Fingerprintアナライザの実装例 |
| 3-2 | PatternAnalyzerProvider.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/PatternAnalyzerProvider.java` | パターンアナライザの実装例 |
| 3-3 | SnowballAnalyzerProvider.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/SnowballAnalyzerProvider.java` | Snowballアナライザの実装例 |

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

```
CommonAnalysisModulePlugin
    |
    +-- getAnalyzers()
    |       +-- FingerprintAnalyzerProvider
    |       +-- PatternAnalyzerProvider
    |       +-- SnowballAnalyzerProvider
    |       +-- ArabicAnalyzerProvider (等30以上の言語)
    |
    +-- getTokenFilters()
    |       +-- LowerCaseTokenFilterFactory
    |       +-- StopTokenFilterFactory
    |       +-- StemmerTokenFilterFactory
    |       +-- NGramTokenFilterFactory
    |       +-- EdgeNGramTokenFilterFactory
    |       +-- ScriptedConditionTokenFilterFactory
    |       +-- (他50以上のフィルタ)
    |
    +-- getTokenizers()
    |       +-- ClassicTokenizerFactory
    |       +-- EdgeNGramTokenizerFactory
    |       +-- KeywordTokenizerFactory
    |       +-- PatternTokenizerFactory
    |       +-- (他)
    |
    +-- getCharFilters()
    |       +-- HtmlStripCharFilterFactory
    |       +-- MappingCharFilterFactory
    |       +-- PatternReplaceCharFilterFactory
    |
    +-- getPreBuiltAnalyzerProviderFactories()
    |       +-- standard, stop, whitespace, simple, keyword等
    |
    +-- getPreConfiguredTokenFilters()
    +-- getPreConfiguredTokenizers()
    +-- getPreConfiguredCharFilters()
```

### データフロー図

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

テキスト文字列 ──> CharFilter ──> Tokenizer ──> TokenFilter Chain ──> TokenStream
    |                                                                    |
    |             CommonAnalysisModulePlugin                             |
    |             (コンポーネント登録)                                      |
    |                                                                    |
    +── _analyze API ─────────────────────────────────── REST応答(tokens)
    +── インデックス時 ──────────────────────────────── 転置インデックス書込
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CommonAnalysisModulePlugin.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/CommonAnalysisModulePlugin.java` | ソース | モジュールプラグインのメインクラス |
| AnalysisPredicateScript.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/AnalysisPredicateScript.java` | ソース | スクリプト条件フィルタ用コンテキスト |
| AnalysisPainlessExtension.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/AnalysisPainlessExtension.java` | ソース | Painless拡張 |
| FingerprintAnalyzerProvider.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/FingerprintAnalyzerProvider.java` | ソース | Fingerprintアナライザ |
| PatternAnalyzerProvider.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/PatternAnalyzerProvider.java` | ソース | パターンアナライザ |
| SnowballAnalyzerProvider.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/SnowballAnalyzerProvider.java` | ソース | Snowballアナライザ |
| ScriptedConditionTokenFilterFactory.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/ScriptedConditionTokenFilterFactory.java` | ソース | スクリプト条件フィルタ |
| StemmerTokenFilterFactory.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/StemmerTokenFilterFactory.java` | ソース | ステマーフィルタ |
| StopTokenFilterFactory.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/StopTokenFilterFactory.java` | ソース | ストップワードフィルタ |
| SynonymTokenFilterFactory.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/SynonymTokenFilterFactory.java` | ソース | シノニムフィルタ |
| NGramTokenFilterFactory.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/NGramTokenFilterFactory.java` | ソース | N-gramフィルタ |
| EdgeNGramTokenFilterFactory.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/EdgeNGramTokenFilterFactory.java` | ソース | Edge N-gramフィルタ |
| LowerCaseTokenFilterFactory.java | `modules/analysis-common/src/main/java/org/opensearch/analysis/common/LowerCaseTokenFilterFactory.java` | ソース | 小文字変換フィルタ |
