Prompts-MCP 686 skills · ai / design / design-pattern / framework / fundamentals / habit / lang / tech-selection /mcp/sse
framework framework/elasticsearch/mapping-design.md medium

elasticsearch-mapping-design

Elasticsearch Mapping 字段类型设计 — text 用于分词全文检索、keyword 用于精确匹配/聚合/排序,避免全 text,长文用 text+keyword 子字段。Use when 建 ES 索引 / 定字段类型 / 排查字段不能聚合或排序时。

字段类型mapping 设计text vs keywordkeyword聚合排序字段
paths
  • *.json
  • *.java

Elasticsearch · Mapping 字段类型设计

本条只管「字段定成什么类型」。中文分词器选哪个见 analyzer-ik.md;定好类型后怎么聚合见 aggregation.md

规则

字段用途 选什么类型 原因
要全文检索(标题、正文、商品名) text 建索引时分词,支持 match 模糊/相关性检索
要精确匹配 / 聚合 / 排序(状态、标签、枚举、ID) keyword 不分词,整体作为 term,可做 term/聚合/sort
既要检索又要聚合的字段(如标题) text + fields.keyword 子字段 field 用于检索,field.keyword 用于聚合排序
数值范围 / 日期范围 integer/long/double/date 支持 range 查询与 date_histogram
不检索只存储返回 text"index": false 省索引空间
关闭动态映射 索引设 "dynamic": "strict" 防止脏字段自动建错类型

text 字段默认不能直接聚合/排序(需开 fielddata,极耗内存,禁用)。要聚合排序就上 keyword 或子字段。

正例

{
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "title":  { "type": "text", "analyzer": "ik_max_word",
                  "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } },
      "status": { "type": "keyword" },
      "price":  { "type": "double" },
      "createdAt": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" }
    }
  }
}

反例

// ❌ 把状态、ID 也定成 text —— 既被分词破坏精确匹配,又无法聚合/排序
{ "properties": {
    "status": { "type": "text" },   // term 查不准、聚合直接报错
    "userId": { "type": "text" }    // 想按 userId 聚合时被迫开 fielddata,吃爆内存
} }

理由:text 会分词,status 被拆后精确过滤失效,且聚合/排序需 fielddata 占大量堆内存;这类字段本质是「值」不是「文档」,应当 keyword

自检

  • [ ] 要分词检索的才用 text,状态/ID/枚举/标签一律 keyword
  • [ ] 既检索又聚合的字段配了 text + keyword 子字段?
  • [ ] 没有为了聚合 text 字段去开 fielddata
  • [ ] 生产索引设了 dynamic: strict,避免脏字段自动建错类型?

相关