mcpField
E
elasticsearch-index-design

elasticsearch-index-design

github.com/elasticデータ・データベース6021.1k 回インストール今日更新
リポジトリ

elasticsearch-index-design について

フィールドのアクセスパターンに基づき、Elasticsearch のインデックスマッピングを設計・レビューするスキルです。型やストレージの問題を避け、型変更時の新規インデックスと再インデックスを計画できます。

主な機能

  1. 01アクセスパターンに応じたフィールド型の選定
  2. 02型の誤りを見つけるマッピングレビュー
  3. 03マッピング膨張とストレージ使用量の抑制
  4. 04明示的なマッピングと設定の設計
  5. 05型変更に伴う再インデックスの計画

活用シーン

  1. 01検索とソート向けの新規インデックス設計
  2. 02フィルター・集計フィールドのマッピング確認
  3. 03新規インデックスと再インデックスによる型修正

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/elastic/agent-skills --skill elasticsearch-index-design

インストール後、Claude Code で/elasticsearch-index-designを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
field-type-decisions.md
mapping-explosion.md
multi-field-patterns.md

詳細

Elasticsearch インデックス設計

アクセスパターンに基づいて明示的なインデックスマッピングを設計し、既存のマッピングで型やストレージに関する誤りを確認します。フィールド型を変更する必要がある場合は、新しいインデックスを作成して再インデックスすることで修正します。

環境設定

このスキルでは、elastic CLI を使って Elasticsearch の操作を実行します。 elastic CLI がインストールされていない場合は、必要であることをユーザーに伝えてください。認証情報を推測したり、HTTP API を直接呼び出したり、ほかの回避策を試したりしないでください。

このスキルでは、HTTP の省略形で操作を記述しています(例:GET /、GET /_cat/indices、GET /{index}/_mapping、 GET /{index}/_settings/index.mode、POST /_query)。このドキュメント末尾の操作表に、各省略形に対応する elastic CLI コマンドを示しています。HTTP API を直接呼び出すのではなく、必ず CLI を使用してください。

プロセス

  1. フィールドごとにアクセスパターンを収集します。 型を選ぶ前に、各フィールドの使用方法を列挙します。すべてのフィールドについて、以下を記録してください。

    • 検索 — 全文検索、フレーズ検索、関連度スコアリングのどれを行いますか?
    • フィルター — 完全一致の語句、語句の集合、プレフィックスのどれを使いますか?
    • 集計 — terms、cardinality、histogram、stats のどれを使いますか?
    • ソート — 結果セットを昇順/降順で並べ替えますか?
    • 取得のみ — _source には返されますが、クエリでは使用されませんか?

    判断では、各フィールドを主なアクセスパターン(検索、完全一致、数値メトリック、日付、ブール値、構造化オブジェクト、取得のみ)のいずれかに分類します。アクセスパターンの情報が不足している場合は作業を進められません。推測せず、ユーザーに確認してください。接続を確認するために GET / を呼び出します。既存のインデックスを確認する場合は、現在のマッピングに基づいて議論できるよう GET /{index}/_mapping を呼び出します。

  2. アクセスパターンに基づいてフィールド型を選びます。 各フィールドには、そのパターンを満たす最小限の型セットを割り当てます。マッピングを提案する前に、フィールド型の判断とマルチフィールドのパターンを読んでください。

    主な判断基準:

    パターンマッピング
    全文検索のみtext(keyword サブフィールドなし)
    フィルター/集計/ソートのみkeyword(text ではありません)
    全文検索 および ソートまたは集計fields.keyword マルチフィールドを持つ text
    小数の価格またはメトリックdouble、float、または scaled_float — text や整数ではありません
    タイムスタンプdate
    真偽値のフラグboolean
    多数の異なるキーを持つ自由形式のキー/値マップflattened — 動的な object ではありません

    マルチフィールドのルール: フィールドを検索 かつ ソート/集計に使用する必要がある場合(例:商品名の name)、keyword サブフィールドを持つ text としてマッピングします。検索には name を、ソートと集計には name.keyword を使用します。この組み合わせのパターンでは、text のみ、または keyword のみとしてマッピングするのは誤りです。

    明示的なマッピングのルール: 新しいインデックスでは、常に PUT /{index} を使って明示的にマッピングを定義してください。本番インデックスで動的マッピングに依存しないでください。最初のドキュメントによって、型が誤った状態(文字列が text、曖昧な数値が keyword)で固定される可能性があります。

    インデックス設定: デプロイ環境で設定できる場合(Self-Managed/Elastic Cloud Hosted)は、同じ PUT /{index} リクエストで number_of_shards と number_of_replicas を明示的に設定します。Serverless ではシャード数とレプリカ数を省略します(Elastic が管理します)。ただし、マッピングは引き続き明示的に指定してください。選択した値を明記するか、デフォルトが適用されることを記録してください。 例 — 検索用に最適化し、さらに name でのソート/集計も行う products インデックス:

    {
      "settings": {
        "number_of_shards": 1,
        "number_of_replicas": 1
      },
      "mappings": {
        "properties": {
          "name": {
            "type": "text",
            "fields": {
              "keyword": { "type": "keyword", "ignore_above": 256 }
            }
          },
          "price": { "type": "double" },
          "created": { "type": "date" },
          "in_stock": { "type": "boolean" }
        }
      }
    }
    

    settings ブロックと mappings ブロックを渡して PUT /products で作成します。GET /products/_mapping で検証します。

  3. マッピング爆発とストレージ肥大化を防ぐ。 大量データを扱うインデックスでは、型の誤りがコストを倍増させます。 マッピング爆発とストレージ肥大化を読み、以下のレビューチェックを適用してください:

    • analyze されているが検索されないフィールド — フィルタと集計にのみ使用されるフィールド(url、HTTP status_code、 tags、ID)は text ではなく keyword でなければなりません。text は容量を浪費します。text に対する集計には fielddata か .keyword サブフィールドが必要ですが、そのフィールドが検索されないのであれば、そのようなサブフィールドは 存在すべきではありません。
    • ignore_above のない message.keyword — 大きな全文本文に対する keyword サブフィールドは、生の文字列全体を 1 つのタームとしてインデックスします。このアンチパターンにフラグを立ててください。全文検索のみが必要な場合は サブフィールドを削除し、範囲を限定した完全一致サブフィールドが本当に必要な場合は ignore_above を追加してください。
    • 動的な自由形式オブジェクト — 数千の異なるキーを持つユーザー提供のキー/値データに対して "dynamic": true を 指定した object は マッピング爆発 を引き起こします。flattened(または strict dynamic / 許可リスト戦略)を 推奨してください。
    • doc_values: false — ヒットで取得されるが、ソート・集計・フィルタのいずれも行われないフィールド (例: 表示専用の session_id)では、keyword に "doc_values": false を設定して大規模時のディスクを節約してください。
    • scaled_float — 精度が限定的なメトリクス(例: response_time_ms)では、ストレージが支配的な場合、 通常の float/double よりも適切な scaling_factor を指定した scaled_float を優先してください。

    不明なフィールドが明示的な要件でない限り、ルートマッピングには "dynamic": "strict" を優先してください。

  4. 設計を適用する: 型が変わる場合は新しいインデックスを作成して reindex する。 Elasticsearch は既存フィールドの 型をその場で変更できません。レビューで誤った型(text→keyword、object→flattened、float→scaled_float、既存フィールドの doc_values 変更)が見つかった場合は、修正には新しいインデックスと reindex が必要であり、稼働中のインデックスに対する マッピング更新では不可能であることを明確に述べてください。

    events のような既存の大量データインデックスを修正するワークフロー:

    1. 修正したマッピングを設計する — 手順 2〜3 のすべての修正を反映した新しいインデックス名(例: events-v2)で行います。
    2. 移行先を作成する — PUT /events-v2 と、完全に修正された mappings(該当する場合は settings も)で行います。
    3. ドキュメントをコピーする — POST /_reindex で行います。大きなインデックスの場合は wait_for_completion=false を 使用し、タスクを追跡します。source: { "index": "events" }、destination: { "index": "events-v2" }。
    4. 検証する — GET /events-v2/_count(source の件数と比較)および GET /events-v2/_mapping(型を確認)で行います。
    5. 切り替える — 検証後に読み取りと書き込みを切り替えます(インデックスエイリアスの交換またはアプリケーション設定)。

    events のレビューパターンに対する修正済みの抜粋例:

    {
      "mappings": {
        "properties": {
          "@timestamp": { "type": "date" },
          "event_id": { "type": "keyword" },
          "session_id": { "type": "keyword", "doc_values": false },
          "url": { "type": "keyword" },
          "status_code": { "type": "keyword" },
          "response_time_ms": { "type": "scaled_float", "scaling_factor": 100 },
          "tags": { "type": "keyword" },
          "message": { "type": "text" },
          "labels": { "type": "flattened" }
        }
      }
    }
    

    これらの型変更に対してその場でのマッピング修正を試みないでください — 拒否されるか、データが不整合な状態になります。 新規のインデックスでは、初回の取り込み前に 1 回 PUT /{index} を実行すれば、reindex を完全に回避できます。

レビューチェックリスト

ユーザーがマッピング JSON と使用状況のメモを提供した場合、次のチェックリストを順に確認してください:

  1. 各フィールドの型を、記載されたアクセスパターンに合わせます(手順 2 を参照)。
  2. フィルタ/集計専用フィールドの text にフラグを立てます。検索とソート/集計が 1 つの論理フィールドを共有している場合は、 マルチフィールドの欠落にフラグを立てます。
  3. 大きな analyze 対象テキストに対して ignore_above のない message.keyword(または類似のもの)にフラグを立てます。
  4. カーディナリティの高い自由形式マップに対する動的な object にフラグを立て、flattened を推奨します。
  5. 取得専用フィールドと数値のストレージ最適化(doc_values: false、scaled_float)を提案します。
  6. 型の変更には新しいインデックスと POST /_reindex が必要であることを述べ、修正したマッピングと reindex 計画を示します。

例

「ユーザーは商品名を検索し、さらにその名前で並べ替えや集計も行います」 — 1 つの論理フィールドに対して 2 つのアクセスパターンがあるため、keyword マルチフィールドを持つ text フィールドを使用します。

{
  "mappings": {
    "properties": {
      "product_name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }
    }
  }
}

「status フィールドはフィルタリングと集計にのみ使い、全文検索には使いません」 — text ではなく、keyword を使用します。

{ "mappings": { "properties": { "status": { "type": "keyword" } } } }

「キーが無制限の自由形式の labels オブジェクト」 — flattened を使ってマッピングの爆発を防ぎます。

{ "mappings": { "properties": { "labels": { "type": "flattened" } } } }

ガイドライン

  • マッピングは最小限に — アクセスパターンで必要なものだけをマッピングします。サブフィールドや解析済み形式を追加するたびに、インデックスデータが増えます。
  • アクセスパターンを推測しない — 型の選択を誤ると、規模が大きくなった際の修正コストが高くなります。
  • 作成後に確認する — 必ず GET /{index}/_mapping で確認します。再インデックス後は GET /{index}/_count を使います。
  • スキルの適用範囲に注意 — インデックス間でドキュメントをコピーするには POST /_reindex を使います(スライス、スロットリング、タスク追跡については reindex スキルを参照してください)。新しいインデックスにファイルを読み込むのは、一括取り込みであり、インデックス設計ではありません。

参考資料

操作

HTTP API(省略形)elastic CLI コマンド
GET /elastic es info
GET /{index}/_mappingelastic es indices get-mapping --index '<index>'
PUT /{index}elastic es indices create --index '<index>' --mappings '<json>' --settings '<json>'
POST /_reindexelastic es reindex --source '<json>' --dest '<json>'
POST /_reindex?wait_for_completion=falseelastic es reindex --wait-for-completion false --source '<json>' --dest '<json>'
GET /{index}/_countelastic es count --index '<index>'

コメント