# 機能設計書 91-Star-Treeマッパー

## 概要

本ドキュメントは、OpenSearchにおけるStar-Treeインデックス用のマッパー定義機能（StarTreeMapper）の設計を記述する。Star-Treeマッパーは、事前集計データを保持するStar-Treeインデックスのフィールドマッピングを定義・管理するための実験的機能である。

### 本機能の処理概要

Star-Treeマッパーは、インデックスマッピング定義内でStar-Treeフィールドを宣言し、ディメンション（次元）とメトリクス（集計指標）の構造を定義する機能を提供する。

**業務上の目的・背景**：大規模データに対する集計クエリのパフォーマンスを向上させるため、Star-Treeインデックスが導入された。Star-Treeマッパーは、このインデックス構造のスキーマ定義を担い、どのフィールドをディメンションとして、どのフィールドをメトリクスとして事前集計するかをマッピングレベルで宣言可能にする。これにより、大規模分析ワークロードにおけるクエリ応答時間を大幅に短縮できる。

**機能の利用シーン**：時系列データや大量のログデータに対して、リアルタイムでの集計分析が必要な場合に使用される。インデックス作成時のマッピング定義で`star_tree`タイプのフィールドを定義することで、Star-Treeインデックスの構築条件を指定する。

**主要な処理内容**：
1. マッピング定義のパース処理 - JSON形式のマッピング定義からStar-Treeフィールドの構成を解析
2. ディメンション構築 - 日付ディメンション及び順序付きディメンションの定義と検証
3. メトリクス構築 - 集計対象メトリクスの定義、基底メトリクスの自動追加、派生メトリクスの自動追加
4. バリデーション - ディメンション数上限、メトリクス数上限、重複検出、型の妥当性チェック
5. StarTreeFieldTypeの構築 - CompositeDataCubeFieldTypeとしてのフィールド型定義

**関連システム・外部連携**：Star-Treeインデックスフレームワーク（compositeindex）、Luceneセグメント構築処理と連携する。

**権限による制御**：インデックス作成・マッピング更新の権限が必要。本機能自体に個別の権限制御はないが、インデックス管理権限に依存する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | Star-Treeマッパーに直接対応するREST API画面は画面機能マッピングに定義されていない |

## 機能種別

データ定義（マッピング定義） / バリデーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| config | Object | Yes | Star-Treeフィールドの構成定義 | Map型であること |
| config.max_leaf_docs | Integer | No | リーフノードの最大ドキュメント数 | 1以上 |
| config.skip_star_node_creation_for_dimensions | String[] | No | スターノード作成をスキップするディメンション名リスト | ordered_dimensionsに含まれること |
| config.ordered_dimensions | List | Yes | 順序付きディメンションのリスト | 最低2つ（date_dimensionとの合計）、上限あり |
| config.date_dimension | Object | No | 日付ディメンションの定義 | date型フィールドであること |
| config.metrics | List | Yes | メトリクス定義のリスト | 数値型フィールドであること |
| config.metrics[].name | String | Yes | メトリクス対象フィールド名 | 既知のフィールドであること |
| config.metrics[].stats | String[] | No | 集計統計種別 | MetricStat列挙値に含まれること |

### 入力データソース

インデックス作成API（Create Index API）またはマッピング更新APIのリクエストボディ内のマッピング定義から入力される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| StarTreeField | Object | パース済みのStar-Treeフィールド定義（ディメンション・メトリクス・設定を含む） |
| StarTreeFieldType | CompositeDataCubeFieldType | Luceneフィールド型としてのStar-Treeフィールド定義 |

### 出力先

インデックスのマッピングメタデータとしてクラスタ状態に保存される。

## 処理フロー

### 処理シーケンス

```
1. TypeParser.parse()でマッピングノードを受け取る
   └─ Builder(name, objBuilder)を生成
2. Builder.parse()でconfigパラメータを解析
   └─ Parameter<StarTreeField>のパーサが起動
3. configマップからmax_leaf_docsを取得
   └─ デフォルト値はStarTreeIndexSettings.STAR_TREE_DEFAULT_MAX_LEAF_DOCSから取得
4. skip_star_node_creation_for_dimensionsを取得
   └─ 空リストがデフォルト
5. buildDimensions()でディメンションを構築
   └─ buildDateDimension()で日付ディメンションを構築（任意）
   └─ ordered_dimensionsから各ディメンションを構築
   └─ 重複チェック、数量チェックを実施
6. buildMetrics()でメトリクスを構築
   └─ 各メトリクスの型チェック、重複チェック
   └─ 基底メトリクスの自動追加
   └─ 派生メトリクスの自動追加
   └─ _doc_countメトリクスを自動追加
7. StarTreeFieldConfigurationを生成
8. StarTreeFieldを生成してBuilderに保持
9. Builder.build()でStarTreeMapperインスタンスを生成
```

### フローチャート

```mermaid
flowchart TD
    A[TypeParser.parse] --> B[Builder生成]
    B --> C[configパラメータ解析]
    C --> D[max_leaf_docs取得]
    D --> E[skip_star_node_in_dims取得]
    E --> F[buildDimensions]
    F --> G{date_dimension?}
    G -->|Yes| H[DateDimension構築]
    G -->|No| I[ordered_dimensions処理]
    H --> I
    I --> J[ディメンションバリデーション]
    J --> K[buildMetrics]
    K --> L[メトリクスバリデーション]
    L --> M[基底/派生メトリクス自動追加]
    M --> N[_doc_count追加]
    N --> O[StarTreeFieldConfiguration生成]
    O --> P[StarTreeField生成]
    P --> Q[StarTreeMapper.build]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-91-01 | 最小ディメンション数 | ディメンション（date_dimension + ordered_dimensions）は合計2つ以上必要 | 常時 |
| BR-91-02 | 最大ディメンション数 | ディメンション数はSTAR_TREE_MAX_DIMENSIONS_DEFAULT以下 | 常時 |
| BR-91-03 | ディメンション重複禁止 | 同一フィールド名のディメンションは定義できない | 常時 |
| BR-91-04 | メトリクス重複禁止 | 同一フィールド名のメトリクスは定義できない | 常時 |
| BR-91-05 | メトリクス型制約 | メトリクスフィールドは数値型でなければならない | 常時 |
| BR-91-06 | max_leaf_docs制約 | max_leaf_docsは1以上でなければならない | 常時 |
| BR-91-07 | 基底メトリクス上限 | 基底メトリクスの合計数はSTAR_TREE_MAX_BASE_METRICS_DEFAULT以下 | 常時 |
| BR-91-08 | _doc_count自動追加 | _doc_countメトリクスは常に自動追加される | 常時 |
| BR-91-09 | 派生メトリクス自動追加 | 基底メトリクスが揃っている場合、派生メトリクスが自動追加される | 常時 |
| BR-91-10 | skip_star_node検証 | skip_star_node_creation_for_dimensionsの値はordered_dimensionsに含まれなければならない | 常時 |

### 計算ロジック

派生メトリクスの自動追加ロジック:
- 全MetricStat値を走査し、派生メトリクス（isDerivedMetric()がtrue）で未追加のものについて、そのbaseMetricsが全て定義済みの場合に自動追加する。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| マッピング保存 | クラスタ状態メタデータ | UPDATE | Star-Treeフィールド定義をインデックスメタデータのマッピングとして保存 |

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

#### クラスタ状態メタデータ（IndexMetadata.mapping）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | mappings | Star-Treeフィールドのシリアライズされたマッピング定義 | CompositeDataCubeFieldTypeとして保存 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IllegalArgumentException | バリデーションエラー | max_leaf_docsが1未満 | 1以上の値を指定 |
| IllegalArgumentException | バリデーションエラー | ordered_dimensionsが未指定 | ordered_dimensionsを定義 |
| IllegalArgumentException | バリデーションエラー | ディメンション数が2未満 | 2つ以上のディメンションを定義 |
| IllegalArgumentException | バリデーションエラー | ディメンション数が上限超過 | ディメンション数を削減 |
| IllegalArgumentException | バリデーションエラー | ディメンションの重複 | 重複するディメンション名を除去 |
| IllegalArgumentException | バリデーションエラー | メトリクスフィールドが非数値型 | 数値型フィールドを指定 |
| IllegalArgumentException | バリデーションエラー | 基底メトリクス数が上限超過 | メトリクス数を削減 |
| IllegalArgumentException | バリデーションエラー | skip_star_node_creation_for_dimensionsにordered_dimensions外の値 | 正しいディメンション名を指定 |
| MapperParsingException | パースエラー | configがMap型でない | 正しいJSON構造を指定 |
| MapperParsingException | パースエラー | ordered_dimensionsがList型でない | 正しい配列形式を指定 |
| MapperParsingException | パースエラー | ドキュメント内にStar-Treeフィールドの値を直接追加 | ドキュメント登録時にStar-Treeフィールドへの値設定は不可 |

### リトライ仕様

リトライ不要。マッピング定義のバリデーションエラーはリクエストの修正が必要。

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

マッピング定義の更新はクラスタ状態更新タスクとして処理され、クラスタマネージャノードでアトミックに適用される。

## パフォーマンス要件

マッピングパース処理はインデックス作成時にのみ実行されるため、特段のパフォーマンス制約はない。ただし、ディメンション・メトリクスの数が増えるとバリデーション処理のコストが増加する。

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

- インデックス作成権限（indices:admin/create）が必要
- マッピング更新権限（indices:admin/mapping/put）が必要
- 本機能は@ExperimentalApiとしてマーク済み

## 備考

- 本機能は実験的API（@ExperimentalApi）であり、将来のバージョンで変更される可能性がある
- StarTreeMapperのコンテンツタイプは "star_tree" である
- ビルドモードは現在OFF_HEAPのみサポート
- parseCreateField()は常にMapperParsingExceptionをスローし、ドキュメント内にStar-Treeフィールドの値を直接追加することはできない
- deriveSource()およびcanDeriveSource()は空実装であり、Star-Treeフィールドはインジェストドキュメントの一部ではない

---

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

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

### 推奨読解順序

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

Star-Treeのコアデータ構造であるDimension、Metric、StarTreeFieldを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Dimension.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/Dimension.java` | ディメンションの基底インターフェース |
| 1-2 | DateDimension.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/DateDimension.java` | 日付ディメンションの特殊処理 |
| 1-3 | Metric.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/Metric.java` | メトリクスの定義（フィールド名+統計種別リスト） |
| 1-4 | MetricStat.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/MetricStat.java` | 統計種別の列挙（AVG, SUM, MIN, MAX等）、派生メトリクスの判定 |
| 1-5 | StarTreeField.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/startree/StarTreeField.java` | ディメンション・メトリクス・設定をまとめるフィールド定義 |
| 1-6 | StarTreeFieldConfiguration.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/startree/StarTreeFieldConfiguration.java` | max_leaf_docs, skip_star_node_in_dims, buildModeの設定 |

**読解のコツ**: MetricStatのisDerivedMetric()とgetBaseMetrics()の関係を理解することが重要。派生メトリクス（例: AVG）は基底メトリクス（SUM, COUNT）から算出される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | StarTreeMapper.java | `server/src/main/java/org/opensearch/index/mapper/StarTreeMapper.java` | TypeParser.parse()がエントリーポイント |

**主要処理フロー**:
1. **518-538行目**: TypeParser.parse() - マッピングノードからBuilderを生成しパースを開始
2. **72-121行目**: Parameter<StarTreeField>のパーサ - configオブジェクトを解析してStarTreeFieldを構築
3. **127-186行目**: buildDimensions() - ディメンションリストの構築とバリデーション
4. **281-370行目**: buildMetrics() - メトリクスリストの構築、基底/派生メトリクスの自動追加
5. **503-506行目**: Builder.build() - StarTreeFieldTypeとStarTreeMapperの生成

#### Step 3: ディメンション構築処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | DimensionFactory.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/DimensionFactory.java` | ディメンションの生成ファクトリ |
| 3-2 | StarTreeMapper.java | `server/src/main/java/org/opensearch/index/mapper/StarTreeMapper.java` | getDimension()メソッド（238-275行目） |

**主要処理フロー**:
- **188-194行目**: buildDateDimension() - date_dimensionフィールドの構築
- **238-275行目**: getDimension() - 個別ディメンションの構築、型チェック
- **430-432行目**: isBuilderAllowedForDimension() - ディメンション対応型の判定

#### Step 4: メトリクス構築処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | StarTreeMapper.java | `server/src/main/java/org/opensearch/index/mapper/StarTreeMapper.java` | buildMetrics()メソッド（281-370行目） |

**主要処理フロー**:
- **373-393行目**: getMetric() - 個別メトリクスの統計種別を解析
- **398-409行目**: addBaseMetrics() - 派生メトリクスの基底メトリクスを追加
- **414-423行目**: addEligibleDerivedMetrics() - 条件を満たす派生メトリクスを自動追加
- **367-368行目**: _doc_countメトリクスの自動追加

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

```
StarTreeMapper.TypeParser.parse()
    |
    +-- Builder(name, objBuilder)
    |
    +-- Builder.parse(name, context, node)
         |
         +-- Parameter<StarTreeField>.parse()
              |
              +-- buildDimensions(name, map, context)
              |    |
              |    +-- buildDateDimension(name, map, context)
              |    |    +-- getDateDimension()
              |    |         +-- DimensionFactory.parseAndCreateDimension()
              |    |
              |    +-- getDimension()
              |         +-- findMapperBuilderByName()
              |         +-- isBuilderAllowedForDimension()
              |         +-- DimensionFactory.parseAndCreateDimension()
              |
              +-- buildMetrics(name, map, context)
              |    |
              |    +-- getMetric()
              |    |    +-- MetricStat.fromTypeName()
              |    |    +-- addBaseMetrics()
              |    |    +-- addEligibleDerivedMetrics()
              |    |
              |    +-- new Metric(DocCountFieldMapper.NAME, DOC_COUNT)
              |
              +-- new StarTreeFieldConfiguration()
              +-- new StarTreeField()
```

### データフロー図

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

マッピング定義JSON ──────> TypeParser.parse() ──────> StarTreeMapper
  (config:                       |                     (StarTreeFieldType)
   max_leaf_docs,          Builder.parse()                   |
   ordered_dimensions,           |                    クラスタ状態メタデータ
   date_dimension,         buildDimensions()                 |
   metrics)                buildMetrics()             Luceneセグメント構築
                                 |                    (Star-Treeインデックス)
                           StarTreeField生成
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| StarTreeMapper.java | `server/src/main/java/org/opensearch/index/mapper/StarTreeMapper.java` | ソース | Star-Treeフィールドマッパーの本体 |
| StarTreeField.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/startree/StarTreeField.java` | ソース | Star-Treeフィールド定義のデータクラス |
| StarTreeFieldConfiguration.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/startree/StarTreeFieldConfiguration.java` | ソース | Star-Tree構築設定 |
| StarTreeIndexSettings.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/startree/StarTreeIndexSettings.java` | ソース | Star-Treeインデックス関連の設定定数 |
| Dimension.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/Dimension.java` | ソース | ディメンションインターフェース |
| DateDimension.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/DateDimension.java` | ソース | 日付ディメンション実装 |
| DimensionFactory.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/DimensionFactory.java` | ソース | ディメンション生成ファクトリ |
| Metric.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/Metric.java` | ソース | メトリクス定義 |
| MetricStat.java | `server/src/main/java/org/opensearch/index/compositeindex/datacube/MetricStat.java` | ソース | 統計種別列挙 |
| CompositeDataCubeFieldType.java | `server/src/main/java/org/opensearch/index/mapper/CompositeDataCubeFieldType.java` | ソース | 複合データキューブフィールド型の基底クラス |
| ParametrizedFieldMapper.java | `server/src/main/java/org/opensearch/index/mapper/ParametrizedFieldMapper.java` | ソース | パラメータ化フィールドマッパーの基底クラス |
| DocCountFieldMapper.java | `server/src/main/java/org/opensearch/index/mapper/DocCountFieldMapper.java` | ソース | _doc_countフィールドマッパー |
