Elasticsearch のデータタイプ詳解:マッピングと検索最適化

Elasticsearch におけるデータ型の定義と運用

Elasticsearch を効果的に利用するためには、各フィールドに対して適切なデータタイプを指定することが不可欠です。正確なマッピング定義は、検索性能の向上とストレージ効率の最適化に直結します。以下の解説は、Elasticsearch 6.x 以降のバージョンを基準としています。

1. 基本データタイプ

インデックス設計の基礎となる主要なデータタイプについて説明します。

1.1 文字列类型:text と keyword

過去のバージョンで使用されていた string 型は廃止され、用途に応じて textkeyword の 2 種類に分割されました。

  • text 型: 全文検索対象となるフィールドに適しています。入力値はアナライザーによってトークン化(分詞)され、インデックスされます。ソートや集計には通常使用できません。
  • keyword 型: 精确な値としての扱いが必要な場合に使用します。分詞されず、そのままインデックスされるため、フィルタリング、ソート、集計に適しています。

マッピング設定例:

PUT online_store
{
  "mappings": {
    "item": {
      "properties": {
        "summary": { 
          "type": "text" 
        },
        "label": { 
          "type": "keyword" 
        }
      }
    }
  }
}

1.2 数値类型

Elasticsearch は 8 種類の数値タイプをサポートしています。メモリ効率と検索速度を考慮し、必要な範囲をカバーする最小のタイプを選択することが推奨されます。

タイプ 概要
byte8 ビット符号付き整数 (-128 ~ 127)
short16 ビット符号付き整数
integer32 ビット符号付き整数
long64 ビット符号付き整数
float32 ビット単精度浮動小数点数
double64 ビット倍精度浮動小数点数
half_float16 ビット半精度浮動小数点数
scaled_floatスケーリング因子を持つ浮動小数点数(例:通貨)

使用例(在庫管理システム):

PUT warehouse
{
  "mappings": {
    "goods": {
      "properties": {
        "item_name": { "type": "text" },
        "stock_count": { "type": "integer" },
        "unit_cost": {
          "type": "scaled_float",
          "scaling_factor": 100
        }
      }
    }
  }
}

1.3 日期类型 (date)

JSON 自体には日期型がないため、Elasticsearch では文字列形式または数値(ミリ秒/秒)として扱います。デフォルトでは UTC に変換され、内部ではミリ秒単位の長整数として保存されます。

複数の日期フォーマットを指定可能で、|| で区切ります。

PUT events
{
  "mappings": {
    "log": {
      "properties": {
        "timestamp": {
          "type": "date",
          "format": "strict_date_optional_time||epoch_millis"
        }
      }
    }
  }
}

データ登録例:

PUT events/log/1
{ "timestamp": "2023-05-20T14:30:00Z" }

PUT events/log/2
{ "timestamp": 1684590600000 }

1.4 布尔类型 (boolean)

真偽値を扱います。内部では true または false として保存されますが、入力時には "true", "false", "1", "0", "yes", "no" などの表現も許容されます。

1.5 二进制类型 (binary)

Base64 エンコードされた文字列としてバイナリデータを保存します。デフォルトでは検索不可ですが、doc_values を有効にすることでスクリプト等での利用が可能になります。

1.6 范围类型 (range)

数値や日期の範囲を単一のフィールドとして保存できます。integer_range, date_range, ip_range などが利用可能です。

PUT hr_system
{
  "mappings": {
    "salary_band": {
      "properties": {
        "pay_range": { "type": "integer_range" },
        "contract_period": { "type": "date_range" }
      }
    }
  }
}

データ例:

PUT hr_system/salary_band/1
{
  "pay_range": { "gte": 300000, "lte": 500000 },
  "contract_period": { "gte": "2023-01-01", "lte": "2023-12-31" }
}

2. 複合データタイプ

構造化されたデータを扱うためのタイプです。

2.1 数组类型 (array)

明示的な配列型は存在せず、同じフィールドに複数の値を指定することで配列として扱われます。ただし、配列内の要素はすべて同じデータタイプである必要があります。

  • 有効:["red", "blue"], [1, 2, 3]
  • 無効:[1, "text"] (混合型は不可)

空の配列 [] はフィールドが存在しないものとして扱われます。

2.2 对象类型 (object)

JSON オブジェクトは内部でフラット化されて保存されます。ドット区切りでネストされたプロパティにアクセス可能です。

PUT personnel
{
  "mappings": {
    "staff": {
      "properties": {
        "profile": {
          "properties": {
            "first_name": { "type": "keyword" },
            "contact": {
              "properties": {
                "email": { "type": "keyword" }
              }
            }
          }
        }
      }
    }
  }
}

2.3 嵌套类型 (nested)

オブジェクトの配列を扱う際、標準の object 型では各オブジェクトのプロパティがすべて平坦化され、関係性が失われる問題があります(例:姓と名の組み合わせが崩れる)。これを解決するのが nested 型です。各オブジェクトは独立した隠しドキュメントとしてインデックスされます。

マッピング定義:

PUT film_database
{
  "mappings": {
    "cast": {
      "properties": {
        "actor": { "type": "nested" }
      }
    }
  }
}

データ登録:

PUT film_database/cast/1
{
  "movie": "Sample Film",
  "actor": [
    { "first": "John", "last": "Doe" },
    { "first": "Jane", "last": "Smith" }
  ]
}

nested クエリによる検索:

GET film_database/_search
{
  "query": {
    "nested": {
      "path": "actor",
      "query": {
        "bool": {
          "must": [
            { "match": { "actor.first": "John" }},
            { "match": { "actor.last": "Doe" }}
          ]
        }
      }
    }
  }
}

3. 地理空間データタイプ

位置情報に基づく検索や集計を可能にするタイプです。

3.1 地理点类型 (geo_point)

緯度と経度のペアを保存します。距離によるソートや、特定の範囲内にある地点の検索(geo_bounding_box など)に利用できます。

入力形式の例:

  • オブジェクト:{ "lat": 35.68, "lon": 139.76 }
  • 文字列:"35.68, 139.76"
  • 配列:[139.76, 35.68] (経度、緯度の順)

店舗_location インデックス例:

PUT store_locations
{
  "mappings": {
    "branch": {
      "properties": {
        "coordinates": { "type": "geo_point" }
      }
    }
  }
}

3.2 地理形状类型 (geo_shape)

ポリゴンなどの複雑な地理的形状を表現できます。geo_point よりも高度な地理検索が必要な場合に使用されますが、設定とクエリが複雑になるため、必要な場合のみ採用を検討します。

4. 特殊データタイプ

特定の用途に最適化されたタイプです。

4.1 IP 类型

IPv4 および IPv6 アドレスを保存します。内部では数値として扱われるため、IP サブネットによる範囲検索などが効率的に行えます。

PUT network_logs
{
  "mappings": {
    "access": {
      "properties": {
        "client_ip": { "type": "ip" }
      }
    }
  }
}

サブネット検索例:

GET network_logs/_search
{
  "query": {
    "term": { "client_ip": "192.168.1.0/24" }
  }
}

4.2 计数数据类型 (token_count)

文字列フィールド内のトークン(単語)数をカウントし、整数としてインデックスします。アナライザーを指定して動作します。

PUT content_analysis
{
  "mappings": {
    "article": {
      "properties": {
        "body": {
          "type": "text",
          "fields": {
            "word_count": {
              "type": "token_count",
              "analyzer": "standard"
            }
          }
        }
      }
    }
  }
}

これにより、body.word_count フィールドに対して単語数でのフィルタリングや集計が可能になります。

タグ: Elasticsearch Mapping data-types nested-query geo-search

6月30日 16:54 投稿