Elasticsearch入門:インデックスとマッピング

Training banner: Japanese text 'Elasticseach入門 インデックスとマッピング' with instructor icon on a dark tech background トレーニング

index の概念

Elasticsearchにおける「インデックス」とは、データを保存し、検索するための単位です。RDBのテーブルに近い存在ですが、Elasticsearchのインデックスは「検索しやすい形」でデータを管理している点が特徴です。インデックスの中にはJSON形式のDocumentが保存され、Documentは複数のFieldで構成されます。RDBのレコード1件が、Document1件に相当します。さらにElasticsearchは、各Fieldのデータを検索に適した形で整理・保持することで、大量データの中から目的の情報を高速に検索できます。Elasticsearchを理解する上では、インデックスを単なる保存場所ではなく、「高速検索を実現するための仕組み」として捉えることが重要です。

document / field の構造

Elasticsearchでは、インデックスの中に「Document」という単位でデータが保存されます。DocumentはJSON形式で表現され、1件のユーザー情報やログデータなど、1つのレコードに相当する情報を保持します。そしてDocumentの中には、「Field」と呼ばれる項目が定義されます。例えば、ユーザー名、投稿日、価格、IPアドレスなどがFieldにあたります。Elasticsearchでは、このFieldごとにデータ型や検索方法が管理されるため、どのようなFieldを持たせるかが検索品質や分析性能に大きく影響します。つまり、DocumentとFieldの設計は、Elasticsearchにおけるデータ構造設計の基本となります。

indexの作成とdocumentの登録

以下は、index作成コマンドです。Kibana – Dev Toolsを起動し、試しに実行してみてください。

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "email": {
        "type": "keyword"
      },
      "first_name": {
        "type": "keyword"
      },
      "biography": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      },
      "age": {
        "type": "integer"
      },
      "join_date": {
        "type": "date"
      }
    }
  }
}

このQueryは、”my-index-000001″ という名前のインデックスを作成し、その中で利用するFieldのデータ型を定義しています。Elasticsearchでは、このようなField定義を「Mapping」と呼びます。

上記のインデックス作成コマンドでは、email、first_name、biography、age、join_date の5つのFieldが定義されています。それぞれのデータ型は以下の通りです。

  • email – keyword型
  • first_name – keyword型
  • biography – text型
  • biography.keyword – keyword型(マルチフィールド)
  • age – integer型
  • join_date – date型

特に biography は、1つのFieldに対して複数のデータ型を持つ「マルチフィールド」として定義されています。これにより、biography は全文検索用の text 型として利用できるだけでなく、biography.keyword を使用して完全一致検索や集計にも利用できます。このようなマルチフィールドは、実際のElasticsearch環境でよく利用される設計パターンです。

biography.keyword の keyword はField Typeではなく、Multi Fieldの名前です。たまたま内部で使用している型も keyword 型であるため混乱しやすいですが、これはElasticsearchで広く使われている慣例です。なお、Multi Fieldの名前は任意に設定できるため、keyword という名前を使用する必要はありません。例えば、raw や exact などの名前を付けることも可能ですが、Elasticsearchの標準的な慣例に合わせて keyword が利用されることが一般的です。

このようにElasticsearchでは、Fieldごとに適切な型を定義することで、検索性能や分析性能を最適化しています。

以下は、index “my-index-000001” に対して、データを投入するコマンドの例です。

PUT my-index-000001/_doc/1
{
  "email": "taro.yamada@example.com",
  "first_name": "Taro",
  "biography": "I am a solution architect specializing in Elasticsearch, cloud technologies, and observability.",
  "age": 35,
  "join_date": "2024-01-15"
}
PUT my-index-000001/_doc/2
{
  "email": "hanako.suzuki@example.com",
  "first_name": "Hanako",
  "biography": "I work as a software engineer and enjoy building scalable web applications using modern technologies.",
  "age": 29,
  "join_date": "2023-06-01"
}
PUT my-index-000001/_doc/3
{
  "email": "john.smith@example.com",
  "first_name": "John",
  "biography": "I am a data analyst with experience in machine learning, data visualization, and business intelligence.",
  "age": 42,
  "join_date": "2022-11-20"
}

上記3つのQueryは、my-index-000001 というインデックスに対して、3件のDocumentを登録するQueryです。/_doc/1、/_doc/2、/_doc/3 の数値はDocument IDであり、それぞれのDocumentを一意に識別するための値です。

登録されるデータはJSON形式で記述されており、以下のFieldに対して値を設定しています。

  • email
  • first_name
  • biography
  • age
  • join_date

例えば、1件目のDocumentでは、メールアドレス、名前、自己紹介文、年齢、入社日が登録されています。登録されたDocumentはMappingで定義されたデータ型に従ってインデックス化されるため、email や first_name に対する完全一致検索、biography に対する全文検索、age の範囲検索、join_date の日付検索などを実行できます。

以下POSTリクエストでもDocumentを作成することが可能です。POSTでデータを登録する場合、IDは自動採番される為、指定する必要はありません。

POST my-index-000001/_doc
{
  "email": "charlie@example.com",
  "first_name": "Charlie",
  "biography": "I am a DevOps engineer with experience in Kubernetes, cloud infrastructure, and CI/CD automation.",
  "age": 27,
  "join_date": "2025-03-10"
}

mapping

Mappingとは、Document内のFieldをどのような型として扱い、どのように検索・分析するかを定義する設定です。例えば、ユーザー名を全文検索したいのか、完全一致で検索したいのかによって、適切なField型は異なります。また、日付や数値として扱うべきデータを正しく定義しておかなければ、範囲検索や集計を効率よく行うことができません。Elasticsearchでは、データ登録時に自動で型推定を行うことも可能ですが、意図しない型で登録されると検索品質や性能に影響する場合があります。そのため、要件に応じて適切にMappingを設計することが重要となります。

multi-fields

Elasticsearchでは、1つのFieldに対して複数の検索方法を持たせるために、「multi-fields」と呼ばれる仕組みがよく利用されます。代表的なのが、”name” を “text” 型、”name.keyword” を “keyword” 型として定義するパターンです。”text” 型は単語単位に分割されるため、全文検索に適しています。一方、”keyword” 型は文字列全体を1つの値として扱うため、完全一致検索や集計、ソートに適しています。例えば、「Tanaka」を部分検索したい場合は “name” を使い、ユーザー名ごとの件数集計や並び替えをしたい場合は “name.keyword” を利用します。このように、用途ごとに適切な検索方法を両立させるため、multi-fieldsはElasticsearchで非常によく使われる設計パターンです。

以下は、multi-fieldsを使用したindex定義例です。

PUT products
{
  "mappings": {
    "properties": {
      "product_id": {
        "type": "keyword"
      },
      "product_name": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      },
      "category": {
        "type": "keyword"
      },
      "price": {
        "type": "double"
      },
      "release_date": {
        "type": "date"
      }
    }
  }
}

この設定では、商品名(product_name)はマルチフィールドとして定義されており、全文検索用の text 型と、集計・ソート用の keyword 型の両方で利用できます。これにより、「商品名で検索する」と「商品名ごとの件数を集計する」を同じデータで実現できます。さらに、カテゴリ、価格、発売日などの商品属性も定義されています。

object field

Object Fieldは、JSONオブジェクトを階層構造のまま保持するためのField Typeです。例えば、従業員情報を管理する場合、社員ID、氏名、メールアドレス、所属部署などを個別のFieldとして定義するのではなく、employee というObjectの配下にまとめて定義できます。これにより、関連する情報を論理的にグループ化できるため、Mappingの可読性やデータ構造の分かりやすさが向上します。また、検索時には employee.name や employee.department のように階層構造を意識した形で利用できます。

PUT employees
{
  "mappings": {
    "properties": {
      "employee": {
        "properties": {
          "id": {
            "type": "keyword"
          },
          "name": {
            "type": "keyword"
          },
          "email": {
            "type": "keyword"
          },
          "department": {
            "type": "keyword"
          },
          "manager": {
            "type": "keyword"
          }
        }
      },
      "hire_date": {
        "type": "date"
      }
    }
  }
}

field type

Elasticsearchでは、Fieldごとにデータ型を定義します。入門者がまず理解しておきたい代表的なField Typeとして、完全一致検索や集計に利用する「keyword」、全文検索に利用する「text」、数値を扱う「integer」「long」「double」、真偽値を扱う「boolean」、日付や時刻を扱う「date」があります。これらを理解することで、多くの業務データを適切に設計できるようになります。一方で、ElasticsearchにはIPアドレスを扱う「ip」、位置情報を扱う「geo_point」、ベクトル検索向けの「dense_vector」など、用途に応じた多数のField Typeが用意されています。利用可能なField Typeの一覧や詳細については、Elastic公式ドキュメントを参照してください。

https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/field-data-types

inverted index

Elasticsearchが高速に検索できる理由の1つが、「Inverted Index(転置インデックス)」と呼ばれるデータ構造です。これは、「どのDocumentにどの単語が含まれているか」をあらかじめ整理して保持する仕組みです。text型Fieldでは、Analyzerによってテキストが単語単位に分割され、その結果がInverted Indexへ登録されます。検索時にはこのInverted Indexを参照することで、全Documentを走査することなく目的のDocumentを高速に検索できます。

RDBのIndexとElasticsearchのInverted Index

RDBのIndexとElasticsearchのInverted Indexは、どちらも検索を高速化するための仕組みですが、その設計目的と得意な検索方法が異なります。

RDBのIndexは、主に完全一致検索や範囲検索を高速化するために利用されます。例えば、name カラムにIndexが設定されている場合、以下のような検索を効率的に実行できます。

SELECT * FROM users WHERE name = 'Tanaka';

この場合、Indexを利用することで全レコードを順番に確認することなく、条件に一致するレコードを素早く見つけることができます。

一方、ElasticsearchのInverted Indexは、全文検索を高速化するための仕組みです。文章を単語単位に分割し、「どの単語がどのDocumentに含まれているか」という情報を管理しています。例えば、「I like Elasticsearch」という文章は、「I」「like」「Elasticsearch」のように単語単位へ分割され、それぞれの単語をキーとした索引が作成されます。そして各索引には、その単語が出現するDocument IDの一覧が登録されます。

そのため、「Elasticsearch」という単語を検索すると、その単語を含むDocumentを即座に見つけることができます。

つまり、RDBのIndexは「特定の値に一致するデータを高速に探す」ことが得意であり、ElasticsearchのInverted Indexは「特定の単語を含む文章を高速に探す」ことが得意です。この違いが、Elasticsearchが大量のテキストデータに対して高速な全文検索を実現できる理由の1つとなっています。

まとめ

Elasticsearchにおけるインデックスは、単なるデータの保存場所ではなく、高速な検索と分析を実現するための重要な仕組みです。DocumentやFieldの構造、Mappingによるデータ型定義、そしてInverted Indexによる全文検索の仕組みを理解することで、なぜElasticsearchが大量データに対して高速な検索を実現できるのかが見えてきます。また、Field TypeやMappingの設計は検索品質や性能に大きく影響するため、要件に応じた適切なインデックス設計が重要です。次回は、検索要件を満たすためのField設計やMapping設計について、より実践的な観点から解説していきます。