# 機能設計書 86-追加マッパー

## 概要

本ドキュメントは、Scaled Float、Token Count、Search As You Type、RankFeature等の追加フィールドマッパーを提供するmapper-extrasモジュールの設計を記述する。

### 本機能の処理概要

mapper-extrasモジュールは、標準のフィールドマッパーに加えて特殊用途のフィールド型を提供する。これにより、スケーリングされた浮動小数点数、トークン数、入力補完向けフィールド、ランキング特徴量フィールドなどの高度なマッピング機能が利用可能となる。

**業務上の目的・背景**：標準のフィールド型だけではカバーできない特殊なユースケース（浮動小数点の精度制御、テキストのトークン数による集計、タイプ途中の検索、学習ランキング用の特徴量格納など）に対応する必要がある。

**機能の利用シーン**：価格データの省メモリ格納（ScaledFloat）、テキストフィールドのトークン数分析（TokenCount）、オートコンプリート機能の実装（SearchAsYouType）、機械学習ランキングの特徴量格納（RankFeature/RankFeatures）。

**主要な処理内容**：
1. ScaledFloatFieldMapper: 浮動小数点値をscaling_factorで乗算しlong値として格納
2. TokenCountFieldMapper: テキストをアナライザでトークン化し、トークン数を数値として格納
3. SearchAsYouTypeFieldMapper: 入力途中の文字列に対してプレフィックス一致検索を可能にするサブフィールドを自動生成
4. RankFeatureFieldMapper: 検索ランキングに使用する特徴量を格納
5. RankFeaturesFieldMapper: 複数の特徴量をスパースに格納
6. RankFeatureMetaFieldMapper: ランク特徴量のメタデータフィールド

**関連システム・外部連携**：RankFeatureQueryBuilderによるランク特徴量クエリ。

**権限による制御**：特になし。標準のインデックスマッピング権限に従う。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | マッピング定義を通じて間接的に使用される |

## 機能種別

データ変換 / フィールドマッピング

## 入力仕様

### 入力パラメータ

**ScaledFloatFieldMapper:**

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| scaling_factor | double | Yes | スケーリング係数 | 正数のみ |
| null_value | double | No | null時のデフォルト値 | - |
| coerce | boolean | No | 型変換の許可 | - |
| ignore_malformed | boolean | No | 不正値の無視 | - |

**TokenCountFieldMapper:**

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| analyzer | String | Yes | トークン分析に使用するアナライザ | null不可 |
| enable_position_increments | boolean | No | 位置増分を有効にするか | デフォルトtrue |
| null_value | integer | No | null時のデフォルト値 | - |

**SearchAsYouTypeFieldMapper:**

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| max_shingle_size | int | No | シングルの最大サイズ | 2-4 |
| analyzer | String | No | インデックスアナライザ | - |

### 入力データソース

インデックスマッピング定義（PUT index/_mapping）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ScaledFloat値 | long | スケーリング後のlong値（内部） |
| トークン数 | integer | テキストのトークン数 |
| サブフィールド | Field[] | SearchAsYouType用の自動生成サブフィールド |
| 特徴量値 | float | RankFeatureの特徴量値 |

### 出力先

Luceneインデックスの各フィールドに格納される。

## 処理フロー

### 処理シーケンス

```
1. マッピング定義の解析
   └─ MapperExtrasModulePlugin.getMappers()で各マッパーのTypeParserを登録
2. ドキュメントインデックス時
   └─ 各FieldMapperのparseCreateField()でフィールド値を変換・格納
3. 検索時
   └─ 各FieldTypeのtermQuery()/rangeQuery()等で検索条件を処理
```

### フローチャート

```mermaid
flowchart TD
    A[マッピング定義] --> B{フィールドタイプ}
    B -->|scaled_float| C[ScaledFloatFieldMapper]
    B -->|token_count| D[TokenCountFieldMapper]
    B -->|search_as_you_type| E[SearchAsYouTypeFieldMapper]
    B -->|rank_feature| F[RankFeatureFieldMapper]
    B -->|rank_features| G[RankFeaturesFieldMapper]
    C --> H[値 * scaling_factor -> long]
    D --> I[テキスト -> アナライザ -> トークン数]
    E --> J[テキスト -> シングル + EdgeNGramサブフィールド]
    F --> K[特徴量値格納]
    G --> L[スパース特徴量マップ格納]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ScaledFloat精度 | 値はscaling_factorで乗算しlong値に丸めて格納される | scaled_floatフィールド |
| BR-02 | TokenCountアナライザ必須 | token_countフィールドにはanalyzer設定が必須 | token_countフィールド |
| BR-03 | SearchAsYouTypeサブフィールド | max_shingle_sizeに応じてサブフィールドが自動生成される | search_as_you_typeフィールド |
| BR-04 | RankFeature検索不可 | RankFeatureフィールドは通常のtermQueryでは検索不可（rank_feature queryのみ） | rank_featureフィールド |

### 計算ロジック

ScaledFloat: `stored_value = Math.round(input_value * scaling_factor)`、検索/集計時は `display_value = stored_value / scaling_factor`

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| インデックス | Luceneフィールド | INSERT | 変換後の値をLuceneドキュメントに格納 |
| 検索 | Luceneフィールド | SELECT | フィールド型に応じたクエリ実行 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | MapperParsingException | ScaledFloatでscaling_factor未設定 | マッピング定義にscaling_factorを追加 |
| - | MapperParsingException | TokenCountでanalyzer未設定 | マッピング定義にanalyzerを追加 |
| - | QueryShardException | RankFeatureに対する通常クエリ | rank_feature queryを使用 |

### リトライ仕様

該当なし。

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

Luceneインデックスのトランザクション管理に従う。

## パフォーマンス要件

ScaledFloatはdouble値をlong値として格納するため、通常のdouble型より省メモリで高速。SearchAsYouTypeはサブフィールドの自動生成によりインデックスサイズが増加するが、プレフィックス検索が高速になる。

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

標準のインデックス操作権限に従う。特別なセキュリティ考慮事項なし。

## 備考

mapper-extrasはOpenSearchのコアモジュールとして同梱されるため、追加インストールは不要。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MapperExtrasModulePlugin.java | `modules/mapper-extras/src/main/java/org/opensearch/index/mapper/MapperExtrasModulePlugin.java` | getMappers()（49-57行目）で5つのマッパー登録。getMetadataMappers()（60-62行目）でRankFeatureメタフィールド登録。getQueries()（65-68行目）でRankFeatureクエリ登録 |

#### Step 2: 各マッパーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ScaledFloatFieldMapper.java | `modules/mapper-extras/src/main/java/org/opensearch/index/mapper/ScaledFloatFieldMapper.java` | CONTENT_TYPE="scaled_float"。scaling_factorによるlong変換ロジック |
| 2-2 | TokenCountFieldMapper.java | `modules/mapper-extras/src/main/java/org/opensearch/index/mapper/TokenCountFieldMapper.java` | CONTENT_TYPE="token_count"。analyzerパラメータ必須 |
| 2-3 | SearchAsYouTypeFieldMapper.java | `modules/mapper-extras/src/main/java/org/opensearch/index/mapper/SearchAsYouTypeFieldMapper.java` | CONTENT_TYPE="search_as_you_type"。FixedShingleFilter/EdgeNGramTokenFilterによるサブフィールド生成 |
| 2-4 | RankFeatureFieldMapper.java | `modules/mapper-extras/src/main/java/org/opensearch/index/mapper/RankFeatureFieldMapper.java` | CONTENT_TYPE="rank_feature" |
| 2-5 | RankFeaturesFieldMapper.java | `modules/mapper-extras/src/main/java/org/opensearch/index/mapper/RankFeaturesFieldMapper.java` | CONTENT_TYPE="rank_features" |

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

```
MapperExtrasModulePlugin
    |
    +-- getMappers()
    |       +-- ScaledFloatFieldMapper.PARSER
    |       +-- TokenCountFieldMapper.PARSER
    |       +-- SearchAsYouTypeFieldMapper.PARSER
    |       +-- RankFeatureFieldMapper.PARSER
    |       +-- RankFeaturesFieldMapper.PARSER
    |
    +-- getMetadataMappers()
    |       +-- RankFeatureMetaFieldMapper.PARSER
    |
    +-- getQueries()
            +-- RankFeatureQueryBuilder
```

### データフロー図

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

マッピング定義 ──────> TypeParser.parse() ──────> FieldMapper生成

ドキュメント値 ──────> parseCreateField()
  - double値          +-- ScaledFloat: * scaling_factor -> long
  - テキスト          +-- TokenCount: analyze -> count -> int
  - テキスト          +-- SAYT: shingle + ngram -> サブフィールド
  - float値           +-- RankFeature: 特徴量格納
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MapperExtrasModulePlugin.java | `modules/mapper-extras/src/main/java/org/opensearch/index/mapper/MapperExtrasModulePlugin.java` | ソース | モジュールプラグイン |
| ScaledFloatFieldMapper.java | `modules/mapper-extras/src/main/java/org/opensearch/index/mapper/ScaledFloatFieldMapper.java` | ソース | スケーリング浮動小数点マッパー |
| TokenCountFieldMapper.java | `modules/mapper-extras/src/main/java/org/opensearch/index/mapper/TokenCountFieldMapper.java` | ソース | トークン数マッパー |
| SearchAsYouTypeFieldMapper.java | `modules/mapper-extras/src/main/java/org/opensearch/index/mapper/SearchAsYouTypeFieldMapper.java` | ソース | 入力補完マッパー |
| RankFeatureFieldMapper.java | `modules/mapper-extras/src/main/java/org/opensearch/index/mapper/RankFeatureFieldMapper.java` | ソース | ランク特徴量マッパー |
| RankFeaturesFieldMapper.java | `modules/mapper-extras/src/main/java/org/opensearch/index/mapper/RankFeaturesFieldMapper.java` | ソース | スパースランク特徴量マッパー |
| RankFeatureMetaFieldMapper.java | `modules/mapper-extras/src/main/java/org/opensearch/index/mapper/RankFeatureMetaFieldMapper.java` | ソース | メタフィールドマッパー |
| RankFeatureQueryBuilder.java | `modules/mapper-extras/src/main/java/org/opensearch/index/query/RankFeatureQueryBuilder.java` | ソース | ランク特徴量クエリビルダー |
