# 機能設計書 89-Sizeマッパー

## 概要

本ドキュメントは、ドキュメントのバイトサイズを記録するSizeマッパープラグイン（mapper-size）の設計を記述する。

### 本機能の処理概要

Sizeマッパーは、ドキュメントの_sourceフィールドのバイトサイズを自動的に`_size`メタデータフィールドとして記録するMetadataFieldMapper実装である。これにより、ドキュメントサイズに基づく検索・ソート・集計が可能となる。

**業務上の目的・背景**：ドキュメントのサイズ監視や、サイズに基づくデータ分析（例: 異常に大きなドキュメントの検出、ストレージ使用量の見積もり）が必要な場面で使用する。

**機能の利用シーン**：ドキュメントサイズの異常検知、インデックスのストレージ効率分析、サイズベースのフィルタリング（大きすぎるドキュメントの除外等）。

**主要な処理内容**：
1. ドキュメントインデックス時にpostParse()で_sourceのバイト長を取得
2. NumberType.INTEGERのフィールドとして値を格納（インデックス、DocValues、ストア対応）
3. enabled設定によりこの機能の有効/無効を切り替え可能

**関連システム・外部連携**：_sourceフィールド。

**権限による制御**：標準のインデックス操作権限に従う。

## 関連画面

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

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| enabled | boolean | No | _sizeフィールドの有効/無効 | デフォルトfalse |

### 入力データソース

ドキュメントの_source（BytesReference）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| _size | integer | ドキュメントの_sourceバイトサイズ |

### 出力先

Luceneインデックスの_sizeメタデータフィールド（NumberType.INTEGER）。インデックス、DocValues、ストアが有効。

## 処理フロー

### 処理シーケンス

```
1. マッピング定義でenabled=trueを設定
   └─ SizeFieldMapper.Builder.build()でSizeFieldMapper生成
2. ドキュメントインデックス時
   └─ postParse(context)が呼ばれる（_sourceがpreParse済みのため）
3. サイズ計算
   └─ context.sourceToParse().source().length()でバイト長取得
4. フィールド格納
   └─ NumberType.INTEGER.createFields(name, value, indexed=true, docValues=true, stored=false, hasPoints=true)
```

### フローチャート

```mermaid
flowchart TD
    A[ドキュメントインデックス] --> B[preParse: _source処理]
    B --> C[postParse: SizeFieldMapper]
    C --> D{enabled?}
    D -->|No| E[何もしない]
    D -->|Yes| F[source().length取得]
    F --> G[NumberType.INTEGER.createFields]
    G --> H[_sizeフィールド格納]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デフォルト無効 | _sizeフィールドはデフォルトで無効（enabled=false） | マッピング定義なし時 |
| BR-02 | postParseで実行 | _sourceが圧縮される前のバイト長を取得するためpostParseで実行 | ドキュメントインデックス時 |
| BR-03 | INTEGER型 | サイズ値はNumberType.INTEGERとして格納される | フィールド生成時 |
| BR-04 | 更新可能設定 | enabled設定はupdateableBoolParamで動的に変更可能 | マッピング更新時 |

### 計算ロジック

`_size = context.sourceToParse().source().length()`

BytesReferenceのlength()メソッドでバイト数を取得。JSONのシリアライズ後のバイトサイズが記録される。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| インデックス | Lucene _sizeフィールド | INSERT | ドキュメントサイズをINTEGERフィールドに格納 |

## エラー処理

### エラーケース一覧

特になし。_sourceが存在する限りlength()は常に成功する。

### リトライ仕様

該当なし。

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

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

## パフォーマンス要件

length()の計算はO(1)であり、パフォーマンスへの影響は最小限。ただし、有効にするとインデックスサイズが若干増加する（INTEGERフィールド分）。

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

特になし。ドキュメントサイズの情報自体はセンシティブデータではない。

## 備考

_sizeフィールドはMetadataFieldMapper（メタデータフィールド）として実装されており、通常のフィールドマッパーとは異なる。NAME="_size"という固定名が使用される。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SizeFieldMapper.java | `plugins/mapper-size/src/main/java/org/opensearch/index/mapper/size/SizeFieldMapper.java` | NAME="_size"（49行目）。MetadataFieldMapperを継承（48行目）。enabled(Explicit<Boolean>)パラメータ（79行目） |

**読解のコツ**: MetadataFieldMapperはParametrizedFieldMapperと異なり、parseCreateFieldではなくpostParseをオーバーライドする。ConfigurableTypeParser（74-77行目）でデフォルト設定とBuilder生成を定義。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MapperSizePlugin.java | `plugins/mapper-size/src/main/java/org/opensearch/plugin/mapper/MapperSizePlugin.java` | getMetadataMappers()でSizeFieldMapper.PARSERを登録 |

#### Step 3: サイズ計算を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SizeFieldMapper.java (postParse) | `plugins/mapper-size/src/main/java/org/opensearch/index/mapper/size/SizeFieldMapper.java` | postParse()（96-103行目）: enabled=falseなら即return。source().length()でバイト長取得。NumberType.INTEGER.createFieldsで格納 |

**主要処理フロー**:
- **98-99行目**: enabled.value()がfalseなら何もせずreturn
- **101行目**: context.sourceToParse().source().length()でバイト長取得
- **102行目**: NumberType.INTEGER.createFields(name, value, true, true, false, true)でフィールド生成
  - indexed=true, docValues=true, stored=false, hasPoints=true

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

```
MapperSizePlugin
    |
    +-- getMetadataMappers() -> SizeFieldMapper.PARSER
            |
SizeFieldMapper
    |
    +-- PARSER (ConfigurableTypeParser)
    |       +-- デフォルト: enabled=false
    |       +-- Builder: enabled設定可能
    |
    +-- postParse(context)
            +-- enabled.value() チェック
            +-- context.sourceToParse().source().length()
            +-- NumberType.INTEGER.createFields()
            +-- context.doc().addAll()
```

### データフロー図

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

ドキュメント _source ──> postParse()
  (BytesReference)          |
                       source().length() = N bytes
                            |
                       NumberType.INTEGER.createFields
                            |
                            v
                       _size = N ──────────> Lucene _sizeフィールド
                                              (indexed, docValues, points)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MapperSizePlugin.java | `plugins/mapper-size/src/main/java/org/opensearch/plugin/mapper/MapperSizePlugin.java` | ソース | プラグインエントリーポイント |
| SizeFieldMapper.java | `plugins/mapper-size/src/main/java/org/opensearch/index/mapper/size/SizeFieldMapper.java` | ソース | Sizeフィールドマッパー本体 |
