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 命令——始终使用 CLI,而不要直接调用 HTTP API。

流程

  1. 收集各字段的访问模式。 在选择类型前,列出每个字段的用途。对每个字段记录:

    • 搜索 — 全文匹配、短语匹配、相关性评分?
    • 筛选 — 精确词项、词项集合、前缀?
    • 聚合 — 词项、基数、直方图、统计信息?
    • 排序 — 在结果集中升序或降序排列?
    • 仅检索 — 在 _source 中返回,但从不用于查询?

    决策方式:将每个字段归入一种主要访问模式(搜索、精确匹配、数值指标、日期、布尔值、结构化对象或仅检索)。缺少访问模式数据时不得继续——应询问用户,而不是自行猜测。调用 GET / 确认连接正常;检查现有索引时,调用 GET /{index}/_mapping,以当前映射为依据展开讨论。

  2. 根据访问模式选择字段类型。 将每个字段映射为满足其模式所需的最精简类型集合。在提出映射前,阅读 字段类型选择 和 多字段模式。

    关键判断:

    模式映射
    仅全文搜索text(不添加 keyword 子字段)
    仅筛选 / 聚合 / 排序keyword(而非 text)
    全文搜索 以及 排序或聚合text,并带有 fields.keyword 多字段
    小数价格或指标double、float 或 scaled_float——不能使用 text 或整数
    时间戳date
    真/假标记boolean
    包含许多不同键的自由格式键值映射flattened——而非动态 object

    多字段规则: 当某个字段必须可搜索 且 可排序或聚合时(例如产品 name),应将其映射为 text,并添加 keyword 子字段——使用 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" }
        }
      }
    }
    

    创建时使用 PUT /products,并传入 settings 和 mappings 块。使用 GET /products/_mapping 验证。

  3. 防止映射膨胀和存储空间过度增长。 对于高流量索引,类型错误会导致成本成倍增加。阅读 映射膨胀和存储空间过度增长,并应用以下审查检查项:

    • 已分析但不会搜索的字段——仅用于筛选和聚合的字段(url、HTTP status_code、 tags、ID)必须使用 keyword,而不是 text。text 会浪费空间;对 text 进行聚合需要 fielddata,或者需要 .keyword 子字段;如果该字段不用于搜索,就不应有此子字段。
    • message.keyword 未设置 ignore_above——大型全文正文上的 keyword 子字段会将整个原始字符串作为一个词项索引。应指出这种反模式;如果只需要全文搜索,就移除该子字段;如果确实需要有长度限制的精确匹配子字段,则添加 ignore_above。
    • 动态自由格式对象——对包含数千个不同键的用户提供键值数据使用 "dynamic": true 的 object,会导致映射膨胀。建议使用 flattened(或严格动态模式/允许列表策略)。
    • doc_values: false——对于会在命中结果中返回、但从不用于排序、聚合或筛选的字段(例如仅用于显示的 session_id),在 keyword 上设置 "doc_values": false,以便在大规模场景下节省磁盘空间。
    • scaled_float——对于精度有界的指标(例如 response_time_ms),当存储成本占主导时,优先使用带有适当 scaling_factor 的 scaled_float,而不是普通的 float/double。

    除非明确需要未知字段,否则优先在根映射上使用 "dynamic": "strict"。

  4. 应用设计:类型变更时创建新索引并重新索引。 Elasticsearch 无法原地更改现有字段的类型。审查发现类型错误时(text→keyword、object→flattened、float→scaled_float、修改现有字段的 doc_values),应明确说明修复需要新索引和重新索引,而不是更新线上索引的映射。

    修正现有高流量索引(例如 events)的工作流:

    1. 设计修正后的映射,在新索引名称(例如 events-v2)下纳入步骤 2–3 中的所有修复。
    2. 使用 PUT /events-v2 创建目标索引,并传入完整的修正后 mappings(以及适用时的 settings)。
    3. 使用 POST /_reindex 复制文档——对于大型索引,使用 wait_for_completion=false 并跟踪任务。 源:{ "index": "events" },目标:{ "index": "events-v2" }。
    4. 使用 GET /events-v2/_count(与源索引的文档数比较)和 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" }
        }
      }
    }
    

    不要尝试原地修复这些类型变更——此类操作会被拒绝,或导致数据不一致。对于全新索引,在首次写入数据前执行一次 PUT /{index} 即可完全避免重新索引。

审查清单

用户提供映射 JSON 和用法说明时,按顺序逐项检查:

  1. 将每个字段的类型与其所述访问模式匹配(参见步骤 2)。
  2. 指出仅用于筛选/聚合的字段使用了 text;指出搜索与排序/聚合共用同一逻辑字段时缺少多字段。
  3. 指出大型已分析文本上的 message.keyword(或类似字段)未设置 ignore_above。
  4. 指出高基数自由格式映射使用了动态 object;建议使用 flattened。
  5. 提出仅用于返回字段和数值字段的存储优化建议(doc_values: false、scaled_float)。
  6. 说明类型变更需要新索引和 POST /_reindex,然后展示修正后的映射和重新索引计划。

示例

“用户搜索产品名称,也会对其排序和进行聚合” — 一个逻辑字段,两种访问模式,因此使用带有 keyword 多字段的 text 字段:

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

“status 字段只用于筛选和聚合,从不进行全文搜索” — 使用 keyword,而非 text:

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

“键名不受限制的自由格式 labels 对象” — 使用 flattened 避免映射爆炸:

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

指南

  • 尽量精简映射 — 仅映射访问模式所需的字段;每个子字段和分析形式都会增加索引数据。
  • 切勿猜测访问模式 — 类型选择错误后,在大规模数据中修正代价很高。
  • 创建后验证 — 始终通过 GET /{index}/_mapping 确认;重新索引后使用 GET /{index}/_count。
  • 跨技能边界 — 在索引之间复制文档时使用 POST /_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>'

评论

支持 Markdown