# 機能設計書 88-Murmur3マッパー

## 概要

本ドキュメントは、フィールド値のMurmur3ハッシュを計算・保存するマッパープラグイン（mapper-murmur3）の設計を記述する。

### 本機能の処理概要

Murmur3マッパーは、フィールド値のMurmur3ハッシュ（128ビットの上位64ビット）を計算し、SortedNumericDocValuesとして保存するフィールドマッパーである。ハッシュ値はcardinality集計の高速化に利用できる。

**業務上の目的・背景**：大量のユニーク値を持つフィールドのcardinality（一意値数）集計において、元の値の代わりにハッシュ値を使用することで集計のメモリ効率と速度を改善する。

**機能の利用シーン**：URLやセッションIDなどの高カーディナリティ文字列フィールドに対するcardinality集計の効率化。

**主要な処理内容**：
1. フィールド値をBytesRefに変換
2. MurmurHash3.hash128()で128ビットハッシュを計算
3. 上位64ビット（h1）をSortedNumericDocValuesFieldとして格納
4. store設定時はStoredFieldとしても格納

**関連システム・外部連携**：Luceneのドキュメントフィールド、cardinality集計。

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

## 関連画面

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

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| stored | boolean | No | ハッシュ値を保存するか | デフォルトfalse |
| meta | Map<String, String> | No | メタデータ | - |

### 入力データソース

ドキュメントのフィールド値（文字列）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ハッシュ値 | long | Murmur3ハッシュの上位64ビット |

### 出力先

LuceneのSortedNumericDocValuesField（必須）、StoredField（store=true時）。

## 処理フロー

### 処理シーケンス

```
1. ドキュメントインデックス時
   └─ parseCreateField(context)
2. 値取得
   └─ コンテキストから文字列値を取得（externalValueまたはparser().textOrNull()）
3. ハッシュ計算
   └─ MurmurHash3.hash128(bytes, offset, length, 0, hash128) -> hash128.h1
4. DocValues格納
   └─ SortedNumericDocValuesField(name, hash)
5. Stored格納（オプション）
   └─ StoredField(name, hash)
```

### フローチャート

```mermaid
flowchart TD
    A[ドキュメント入力] --> B{値がnull?}
    B -->|Yes| C[何もしない]
    B -->|No| D[BytesRefに変換]
    D --> E["MurmurHash3.hash128()"]
    E --> F[h1 = 上位64ビット取得]
    F --> G[SortedNumericDocValuesField追加]
    G --> H{stored?}
    H -->|Yes| I[StoredField追加]
    H -->|No| J[完了]
    I --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 検索不可 | Murmur3フィールドはtermQuery等での直接検索ができない | Murmur3FieldType.termQuery() |
| BR-02 | インデックス無効 | IndexOptionsはNONE（インデックス無効）に設定される | Defaults.FIELD_TYPE |
| BR-03 | DocValues有効 | SortedNumericDocValuesは常に有効 | 集計で使用するため |
| BR-04 | ハッシュシード | ハッシュのシード値は0固定 | hash128の第4引数 |
| BR-05 | null値スキップ | null値の場合はフィールドを追加しない | parseCreateField |

### 計算ロジック

`hash = MurmurHash3.hash128(value.getBytes(), offset, length, seed=0).h1`

MurmurHash3は非暗号化ハッシュ関数であり、均一な分布特性を持つ。128ビットハッシュの上位64ビットのみを使用する。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| インデックス | Lucene DocValues | INSERT | ハッシュ値をSortedNumericDocValuesに格納 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | QueryShardException | termQuery等の検索クエリ実行 | Murmur3フィールドは検索不可。集計用途のみ |

### リトライ仕様

該当なし。

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

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

## パフォーマンス要件

MurmurHash3は高速な非暗号化ハッシュであり、インデックス時のオーバーヘッドは最小限。long値として格納されるためストレージ効率が良い。

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

MurmurHash3は暗号化ハッシュではないため、セキュリティ目的では使用しないこと。

## 備考

Murmur3フィールドは主にcardinality集計の内部最適化で使用される。直接的な検索用途には向かない。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Murmur3FieldMapper.java | `plugins/mapper-murmur3/src/main/java/org/opensearch/index/mapper/murmur3/Murmur3FieldMapper.java` | CONTENT_TYPE="murmur3"（64行目）。Defaults.FIELD_TYPE（67-71行目）でIndexOptions.NONE。Murmur3FieldType（106-131行目）でtermQuery不可 |

**読解のコツ**: Murmur3FieldTypeはMappedFieldTypeを直接継承し、termQuery()（128-130行目）でQueryShardExceptionをスロー。fielddataBuilder()（117-120行目）でSortedNumericIndexFieldDataを返す。

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

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

#### Step 3: ハッシュ計算を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Murmur3FieldMapper.java (parseCreateField) | `plugins/mapper-murmur3/src/main/java/org/opensearch/index/mapper/murmur3/Murmur3FieldMapper.java` | 148-163行目: 値取得 -> BytesRef変換 -> MurmurHash3.hash128() -> h1取得 -> DocValues/StoredField追加 |

**主要処理フロー**:
- **149-154行目**: externalValueまたはparser().textOrNull()で値取得
- **156行目**: BytesRefに変換
- **157行目**: MurmurHash3.hash128()で128ビットハッシュ計算、h1（上位64ビット）取得
- **158行目**: SortedNumericDocValuesField追加
- **159-161行目**: store設定時はStoredField追加

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

```
MapperMurmur3Plugin
    |
    +-- getMappers() -> Murmur3FieldMapper.PARSER
            |
Murmur3FieldMapper
    |
    +-- Builder.build()
    |       +-- Murmur3FieldType(name, stored, meta)
    |
    +-- parseCreateField(context)
            +-- context.externalValue() / parser().textOrNull()
            +-- new BytesRef(value.toString())
            +-- MurmurHash3.hash128(bytes, offset, length, 0, hash128)
            +-- SortedNumericDocValuesField(name, hash128.h1)
            +-- StoredField(name, hash128.h1) [if stored]
```

### データフロー図

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

文字列値 ──────> BytesRef変換
                    |
                MurmurHash3.hash128(bytes, 0, len, 0)
                    |
                hash128.h1 (上位64bit) ──────> SortedNumericDocValuesField
                                                + StoredField (optional)
```

### 関連ファイル一覧

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