elasticsearch-index-design
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseElasticsearch Index Design
Elasticsearch 索引设计
Design explicit index mappings from access patterns, review existing mappings for type and storage mistakes, and apply
corrections through a new index plus reindex when field types must change.
<!-- begin-partial: preamble -->根据访问模式设计明确的索引映射,审核现有映射中的类型和存储错误,并在必须更改字段类型时,通过创建新索引并重新索引的方式应用修正。
<!-- begin-partial: preamble -->Environment Configuration
环境配置
This skill executes Elasticsearch operations through the CLI. If the
CLI is not installed, tell the user what it is needed for. Do
not guess credentials, call the HTTP API directly, or attempt other workarounds.
elasticelasticThis skill references operations in HTTP-shorthand form (e.g., , , ,
, ). The Operations table at the end of this document
maps each shorthand to the equivalent CLI command — always use the CLI rather than calling the HTTP API
directly.
<!-- end-partial: preamble -->GET /GET /_cat/indicesGET /{index}/_mappingGET /{index}/_settings/index.modePOST /_queryelastic本技能通过 CLI执行Elasticsearch操作。若未安装 CLI,请告知用户其用途。请勿猜测凭据、直接调用HTTP API或尝试其他变通方法。
elasticelastic本技能以HTTP简写形式引用操作(例如、、、、)。本文档末尾的操作表格将每个简写映射为等效的 CLI命令——请始终使用CLI而非直接调用HTTP API。
<!-- end-partial: preamble -->GET /GET /_cat/indicesGET /{index}/_mappingGET /{index}/_settings/index.modePOST /_queryelasticProcess
流程
-
Gather access patterns per field. Before choosing types, list how each field is used. For every field capture:
- Search — full-text match, phrase, relevance scoring?
- Filter — exact term, terms set, prefix?
- Aggregate — terms, cardinality, histogram, stats?
- Sort — ascending/d descending in result sets?
- Retrieve only — returned in but never queried?
_source
The decision: classify each field into one primary access pattern (search, exact, numeric metric, date, boolean, structured object, or retrieve-only). Missing access-pattern data is a blocker — ask the user rather than guessing. Callto confirm connectivity; when reviewing an existing index, callGET /to ground the discussion in the current mapping.GET /{index}/_mapping -
Choose field types from access patterns. Map each field to the minimal type set that satisfies its pattern. Read Field Type Decisions and Multi-Field Patterns before proposing mappings.Key judgments:
Pattern Mapping Full-text search only (no keyword sub-field)textFilter / agg / sort only (notkeyword)textFull-text search and sort or aggregation withtextmulti-fieldfields.keywordDecimal price or metric ,double, orfloat— notscaled_floator integertextTimestamp dateTrue/false flag booleanFree-form key/value map with many distinct keys — not dynamicflattenedobjectMulti-field rule: When a field must be searchable and sortable/aggregatable (e.g. product), map it asnamewith atextsub-field — search onkeyword, sort and aggregate onname. Mapping as onlyname.keywordor onlytextis wrong for that combined pattern.keywordExplicit mapping rule: For new indices, always define mappings explicitly with. Do not rely on dynamic mapping for production indices — the first document can lock in wrong types (strings asPUT /{index}, ambiguous numbers astext).keywordIndex settings: Set deliberateandnumber_of_shardsin the samenumber_of_replicasrequest when the deployment allows it (Self-Managed / Elastic Cloud Hosted). On Serverless, omit shard and replica counts (Elastic manages them); still supply explicit mappings. State chosen values or document that defaults apply.PUT /{index}Example —index optimized for search plus sort/agg on name:productsjson{ "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" } } } }Create withpassing thePUT /productsandsettingsblocks. Verify withmappings.GET /products/_mapping -
Guard against mapping explosion and storage bloat. On high-volume indices, type mistakes multiply cost. Read Mapping Explosion and Storage Bloat and apply these review checks:
- Analyzed-but-not-searched fields — Fields used only for filter and aggregation (, HTTP
url,status_code, IDs) must betags, notkeyword.textwastes space; aggregations ontextrequire fielddata or atextsub-field that should not exist if the field is not searched..keyword - without
message.keyword— A keyword sub-field on a large full-text body indexes the entire raw string as one term. Flag this anti-pattern; remove the sub-field when only full-text search is needed, or addignore_abovewhen a bounded exact-match sub-field is truly required.ignore_above - Dynamic free-form objects — with
objecton user-supplied key/value data with thousands of distinct keys causes mapping explosion. Recommend"dynamic": true(or strict dynamic / allowlist strategy).flattened - — On fields retrieved in hits but never sorted, aggregated, or filtered (e.g. display-only
doc_values: false), setsession_idon"doc_values": falseto save disk at scale.keyword - — For metrics with bounded precision (e.g.
scaled_float), preferresponse_time_mswith an appropriatescaled_floatover plainscaling_factor/floatwhen storage dominates.double
Preferon the root mapping unless unknown fields are an explicit requirement."dynamic": "strict" - Analyzed-but-not-searched fields — Fields used only for filter and aggregation (
-
Apply design: create new index and reindex when types change. Elasticsearch cannot change an existing field's type in place. When review finds wrong types (text→keyword, object→flattened, float→scaled_float, doc_values changes on existing fields), state clearly that fixes require a new index and reindex — not a mapping update on the live index.Workflow for correcting an existing high-volume index such as:
events- Design the corrected mapping on a new index name (e.g. ) incorporating all fixes from steps 2–3.
events-v2 - Create the destination with and the full corrected
PUT /events-v2(andmappingswhere applicable).settings - Copy documents with — for large indices use
POST /_reindexand track the task. Source:wait_for_completion=false, destination:{ "index": "events" }.{ "index": "events-v2" } - Verify with (compare to source count) and
GET /events-v2/_count(confirm types).GET /events-v2/_mapping - Cut over reads and writes (index alias swap or application config) after validation.
Example corrected excerpt for thereview pattern:eventsjson{ "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" } } } }Do not attempt in-place mapping fixes for these type changes — they are rejected or leave data inconsistent. For greenfield indices, a singlebefore first ingest avoids reindex entirely.PUT /{index} - Design the corrected mapping on a new index name (e.g.
-
收集每个字段的访问模式。在选择类型之前,列出每个字段的使用方式。为每个字段记录:
- 搜索——是否为全文匹配、短语匹配、相关性评分?
- 过滤——是否为精确术语、术语集、前缀匹配?
- 聚合——是否为术语、基数、直方图、统计?
- 排序——结果集中是否需要升序/降序排列?
- 仅检索——仅在中返回但从不查询?
_source
决策:将每个字段归类为一种主要访问模式(搜索、精确匹配、数值指标、日期、布尔值、结构化对象或仅检索)。缺少访问模式数据会阻碍进程——请询问用户而非猜测。调用确认连通性;审核现有索引时,调用GET /以基于当前映射展开讨论。GET /{index}/_mapping -
根据访问模式选择字段类型。将每个字段映射到满足其模式的最小类型集合。在提出映射方案之前,请阅读字段类型决策和多字段模式。关键判断:
模式 映射方案 仅全文搜索 (无keyword子字段)text仅过滤/聚合/排序 (而非keyword)text全文搜索且排序或聚合 搭配text多字段fields.keyword十进制价格或指标 、double或float——而非scaled_float或整数text时间戳 date布尔标记 boolean包含大量不同键的自由形式键值对 ——而非动态flattenedobject多字段规则:当一个字段必须同时支持搜索和排序/聚合时(例如产品),将其映射为带name子字段的keyword——在text上执行搜索,在name上执行排序和聚合。仅映射为name.keyword或仅映射为text对于这种组合模式来说都是错误的。keyword显式映射规则:对于新索引,始终通过显式定义映射。生产环境索引请勿依赖动态映射——首个文档可能会锁定错误类型(字符串被识别为PUT /{index}、模糊数字被识别为text)。keyword索引设置:在部署允许的情况下(自托管/Elastic Cloud托管),在同一个请求中设置明确的PUT /{index}和number_of_shards。在Serverless环境中,省略分片和副本计数(由Elastic管理);仍需提供显式映射。说明所选值或记录使用默认值。number_of_replicas示例——针对搜索及名称排序/聚合优化的索引:productsjson{ "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 -
防止映射爆炸和存储膨胀。在高容量索引上,类型错误会成倍增加成本。阅读映射爆炸与存储膨胀并应用以下审核检查:
- 仅用于过滤聚合的已分析字段——仅用于过滤和聚合的字段(、HTTP
url、status_code、ID)必须设为tags,而非keyword。text会浪费空间;在text上执行聚合需要fielddata或text子字段,若字段无需搜索则不应存在该子字段。.keyword - 无的
ignore_above——大型全文内容上的keyword子字段会将整个原始字符串作为单个词项索引。标记这种反模式;仅需全文搜索时移除该子字段,或在确实需要有界精确匹配子字段时添加message.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" - 仅用于过滤聚合的已分析字段——仅用于过滤和聚合的字段(
-
应用设计:类型变更时创建新索引并重新索引。Elasticsearch无法在原地修改现有字段的类型。当审核发现错误类型(text→keyword、object→flattened、float→scaled_float、现有字段的doc_values变更)时,明确说明修复需要新索引和重新索引——而非对实时索引进行映射更新。修正现有高容量索引(如)的工作流程:
events- 设计修正后的映射,使用新索引名称(例如),整合步骤2-3中的所有修复内容。
events-v2 - 创建目标索引,通过传入完整的修正后
PUT /events-v2(以及适用的mappings)。settings - 复制文档,使用——对于大型索引,使用
POST /_reindex并跟踪任务。源:wait_for_completion=false,目标:{ "index": "events" }。{ "index": "events-v2" } - 验证,使用(与源索引计数对比)和
GET /events-v2/_count(确认类型)。GET /events-v2/_mapping - 切换流量,验证完成后切换读写操作(索引别名交换或应用配置修改)。
索引审核模式的修正示例片段:eventsjson{ "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} - 设计修正后的映射,使用新索引名称(例如
Review checklist
审核清单
When the user supplies a mapping JSON and usage notes, walk this checklist in order:
- Match each field's type to its stated access pattern (see step 2).
- Flag on filter/agg-only fields; flag missing multi-fields where search and sort/agg share one logical field.
text - Flag (or similar) without
message.keywordon large analyzed text.ignore_above - Flag dynamic on high-cardinality free-form maps; recommend
object.flattened - Propose retrieve-only and numeric storage optimizations (,
doc_values: false).scaled_float - State that type changes require a new index and , then show the corrected mapping and reindex plan.
POST /_reindex
当用户提供映射JSON和使用说明时,按以下顺序执行检查:
- 匹配每个字段的类型与其指定的访问模式(见步骤2)。
- 标记仅用于过滤/聚合的字段使用类型的情况;标记同一逻辑字段需同时支持搜索和排序/聚合但缺少多字段的情况。
text - 标记大型已分析文本上无的
ignore_above(或类似字段)。message.keyword - 标记高基数自由形式映射使用动态的情况;建议使用
object。flattened - 提出仅检索字段和数值存储优化方案(、
doc_values: false)。scaled_float - 说明类型变更需要新索引和,然后展示修正后的映射和重新索引计划。
POST /_reindex
Examples
示例
"Users search product names and also sort and aggregate on them" — one logical field, two access patterns, so use a
field with a multi-field:
textkeywordjson
{
"mappings": {
"properties": {
"product_name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }
}
}
}"A field is only ever filtered and aggregated, never full-text searched" — use , not :
statuskeywordtextjson
{ "mappings": { "properties": { "status": { "type": "keyword" } } } }"Free-form object with unbounded keys" — avoid mapping explosion with :
labelsflattenedjson
{ "mappings": { "properties": { "labels": { "type": "flattened" } } } }"用户搜索产品名称,同时也对其进行排序和聚合"——一个逻辑字段,两种访问模式,因此使用带多字段的字段:
keywordtextjson
{
"mappings": {
"properties": {
"product_name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }
}
}
}"字段仅用于过滤和聚合,从不进行全文搜索"——使用而非:
statuskeywordtextjson
{ "mappings": { "properties": { "status": { "type": "keyword" } } } }"包含无限键的自由形式对象"——使用避免映射爆炸:
labelsflattenedjson
{ "mappings": { "properties": { "labels": { "type": "flattened" } } } }Guidelines
指南
- Minimal mapping — Map only what access patterns require; every sub-field and analyzed form adds indexed data.
- Never guess access patterns — Wrong type choice is expensive to fix at scale.
- Verify after create — Always confirm with ; use
GET /{index}/_mappingafter reindex.GET /{index}/_count - Cross-skill boundary — Copying documents between indices is (see the reindex skill for slicing, throttling, and task tracking). Loading files into a new index is bulk ingest, not index design.
POST /_reindex
- 最小化映射——仅映射访问模式所需的内容;每个子字段和已分析形式都会增加索引数据量。
- 绝不猜测访问模式——错误的类型选择在大规模场景下修复成本极高。
- 创建后验证——始终使用确认;重新索引后使用
GET /{index}/_mapping验证。GET /{index}/_count - 跨技能边界——在索引之间复制文档使用(有关分片、限流和任务跟踪,请参阅重新索引技能)。将文件加载到新索引属于批量导入,而非索引设计范畴。
POST /_reindex
Reference material
参考资料
- Field Type Decisions — access-pattern-to-type table and common mistakes
- Multi-Field Patterns — text+keyword, , anti-patterns
ignore_above - Mapping Explosion and Storage Bloat — ,
flattened, dynamic objectsdoc_values
- 字段类型决策——访问模式到类型的对应表及常见错误
- 多字段模式——text+keyword、、反模式
ignore_above - 映射爆炸与存储膨胀——、
flattened、动态对象doc_values
Operations
操作
| HTTP API (shorthand) | |
|---|---|
| |
| |
| |
| |
| |
| |
| HTTP API(简写形式) | |
|---|---|
| |
| |
| |
| |
| |
| |