Elasticsearch映射管理 #

一、映射概述 #

1.1 什么是映射 #

映射定义了文档如何存储和索引,包括:

  • 字段的数据类型
  • 字段如何被索引
  • 字段如何被搜索
text
映射作用
├── 数据类型定义
│   └── 确定字段存储格式
├── 索引配置
│   └── 是否索引、如何分词
├── 搜索配置
│   └── 如何搜索、如何排序
└── 存储优化
    └── 压缩、存储策略

1.2 映射类型 #

类型 说明
动态映射 自动检测字段类型
显式映射 手动定义字段类型

二、动态映射 #

2.1 动态映射规则 #

Elasticsearch自动检测并添加字段:

json
PUT /products/_doc/1
{
  "name": "iPhone 15",
  "price": 999,
  "in_stock": true,
  "tags": ["phone", "apple"]
}

自动生成的映射:

json
{
  "products": {
    "mappings": {
      "properties": {
        "name": { "type": "text", "fields": { "keyword": { "type": "keyword" } } },
        "price": { "type": "long" },
        "in_stock": { "type": "boolean" },
        "tags": { "type": "text", "fields": { "keyword": { "type": "keyword" } } }
      }
    }
  }
}

2.2 类型推断规则 #

JSON值 Elasticsearch类型
null 不添加字段
true/false boolean
整数 long
浮点数 float
字符串 text + keyword
数组 取决于第一个非空元素
对象 object

2.3 动态映射配置 #

bash
PUT /products
{
  "mappings": {
    "dynamic": "true",
    "properties": {
      "name": { "type": "text" }
    }
  }
}

dynamic参数值

说明
true 自动添加新字段(默认)
false 新字段不索引但存在于_source
strict 遇到新字段报错
runtime 新字段作为运行时字段

2.4 动态模板 #

bash
PUT /products
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_keyword": {
          "match_mapping_type": "string",
          "match": "*_code",
          "mapping": {
            "type": "keyword"
          }
        }
      },
      {
        "strings_as_text": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      },
      {
        "longs_as_integer": {
          "match_mapping_type": "long",
          "mapping": {
            "type": "integer"
          }
        }
      }
    ]
  }
}

2.5 动态模板匹配规则 #

参数 说明
match 匹配字段名
unmatch 排除字段名
match_mapping_type 匹配数据类型
path_match 匹配字段路径
path_unmatch 排除字段路径

示例:

bash
PUT /logs
{
  "mappings": {
    "dynamic_templates": [
      {
        "message_field": {
          "match_mapping_type": "string",
          "path_match": "message.*",
          "mapping": {
            "type": "text"
          }
        }
      },
      {
        "status_codes": {
          "match": "status_*",
          "mapping": {
            "type": "keyword"
          }
        }
      }
    ]
  }
}

三、显式映射 #

3.1 创建索引时定义映射 #

bash
PUT /products
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "standard"
      },
      "description": {
        "type": "text",
        "analyzer": "standard"
      },
      "price": {
        "type": "scaled_float",
        "scaling_factor": 100
      },
      "brand": {
        "type": "keyword"
      },
      "category": {
        "type": "keyword"
      },
      "tags": {
        "type": "keyword"
      },
      "in_stock": {
        "type": "boolean"
      },
      "created_at": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss"
      },
      "location": {
        "type": "geo_point"
      }
    }
  }
}

3.2 添加新字段 #

bash
PUT /products/_mapping
{
  "properties": {
    "rating": {
      "type": "float"
    },
    "reviews": {
      "type": "integer"
    }
  }
}

3.3 查看映射 #

bash
GET /products/_mapping

3.4 查看特定字段映射 #

bash
GET /products/_mapping/field/name

GET /products/_mapping/field/name,price

四、字段属性配置 #

4.1 通用属性 #

json
{
  "properties": {
    "field_name": {
      "type": "text",
      "index": true,
      "doc_values": true,
      "store": false,
      "enabled": true,
      "null_value": "NULL",
      "ignore_above": 256
    }
  }
}
属性 说明 默认值
type 字段类型 -
index 是否索引 true
doc_values 是否存储doc_values true
store 是否单独存储 false
enabled 是否处理字段 true
null_value 空值替换 -
ignore_above 超过长度不索引 -

4.2 text字段属性 #

json
{
  "properties": {
    "content": {
      "type": "text",
      "analyzer": "standard",
      "search_analyzer": "standard",
      "fielddata": false,
      "index": true,
      "norms": true,
      "index_options": "positions",
      "term_vector": "no"
    }
  }
}
属性 说明 默认值
analyzer 索引分析器 standard
search_analyzer 搜索分析器 同analyzer
fielddata 是否启用fielddata false
norms 是否存储规范 true
index_options 索引选项 positions

4.3 keyword字段属性 #

json
{
  "properties": {
    "status": {
      "type": "keyword",
      "ignore_above": 256,
      "index": true,
      "doc_values": true,
      "normalizer": "lowercase"
    }
  }
}

4.4 数值字段属性 #

json
{
  "properties": {
    "price": {
      "type": "scaled_float",
      "scaling_factor": 100,
      "coerce": true,
      "ignore_malformed": false
    }
  }
}

4.5 日期字段属性 #

json
{
  "properties": {
    "created_at": {
      "type": "date",
      "format": "yyyy-MM-dd HH:mm:ss||epoch_millis",
      "locale": "zh_CN",
      "ignore_malformed": false
    }
  }
}

五、多字段(Multi-fields) #

5.1 基本用法 #

json
{
  "properties": {
    "title": {
      "type": "text",
      "fields": {
        "keyword": {
          "type": "keyword",
          "ignore_above": 256
        },
        "english": {
          "type": "text",
          "analyzer": "english"
        }
      }
    }
  }
}

5.2 使用方式 #

bash
GET /products/_search
{
  "query": {
    "match": {
      "title": "iPhone"
    }
  }
}

GET /products/_search
{
  "query": {
    "term": {
      "title.keyword": "iPhone 15 Pro"
    }
  }
}

GET /products/_search
{
  "query": {
    "match": {
      "title.english": "phones"
    }
  }
}

六、嵌套对象映射 #

6.1 object类型 #

json
{
  "properties": {
    "user": {
      "type": "object",
      "properties": {
        "name": { "type": "text" },
        "email": { "type": "keyword" },
        "address": {
          "type": "object",
          "properties": {
            "city": { "type": "keyword" },
            "street": { "type": "text" }
          }
        }
      }
    }
  }
}

6.2 nested类型 #

json
{
  "properties": {
    "comments": {
      "type": "nested",
      "properties": {
        "user": { "type": "keyword" },
        "message": { "type": "text" },
        "created_at": { "type": "date" }
      }
    }
  }
}

6.3 nested查询 #

bash
GET /posts/_search
{
  "query": {
    "nested": {
      "path": "comments",
      "query": {
        "bool": {
          "must": [
            { "term": { "comments.user": "alice" } },
            { "match": { "comments.message": "great" } }
          ]
        }
      },
      "inner_hits": {}
    }
  }
}

七、运行时字段 #

7.1 定义运行时字段 #

bash
PUT /products
{
  "mappings": {
    "runtime": {
      "price_with_tax": {
        "type": "double",
        "script": {
          "source": "emit(doc['price'].value * 1.1)"
        }
      }
    },
    "properties": {
      "name": { "type": "text" },
      "price": { "type": "double" }
    }
  }
}

7.2 查询时定义运行时字段 #

bash
GET /products/_search
{
  "runtime_mappings": {
    "price_with_tax": {
      "type": "double",
      "script": {
        "source": "emit(doc['price'].value * 1.1)"
      }
    }
  },
  "query": {
    "range": {
      "price_with_tax": {
        "lte": 1000
      }
    }
  }
}

7.3 运行时字段特点 #

text
运行时字段
├── 优点
│   ├── 不增加索引大小
│   ├── 灵活,可随时修改
│   └── 不需要重建索引
└── 缺点
    ├── 查询性能较低
    └── 不能用于排序和聚合优化

八、元数据字段 #

8.1 _source字段 #

json
{
  "mappings": {
    "_source": {
      "enabled": true,
      "excludes": ["sensitive_data"],
      "includes": ["*"]
    }
  }
}

8.2 _routing字段 #

json
{
  "mappings": {
    "_routing": {
      "required": true
    }
  }
}

8.3 _index字段 #

bash
GET /_search
{
  "query": {
    "term": {
      "_index": "products"
    }
  }
}

九、映射限制 #

9.1 字段数量限制 #

bash
PUT /products/_settings
{
  "index.mapping.total_fields.limit": 2000
}

9.2 字段深度限制 #

bash
PUT /products/_settings
{
  "index.mapping.depth.limit": 20
}

9.3 嵌套字段限制 #

bash
PUT /products/_settings
{
  "index.mapping.nested_fields.limit": 50,
  "index.mapping.nested_objects.limit": 10000
}

十、映射更新策略 #

10.1 添加字段 #

bash
PUT /products/_mapping
{
  "properties": {
    "new_field": {
      "type": "keyword"
    }
  }
}

10.2 修改字段类型 #

已存在的字段类型不能直接修改,需要重建索引:

bash
PUT /products_v2
{
  "mappings": {
    "properties": {
      "name": { "type": "keyword" }
    }
  }
}

POST /_reindex
{
  "source": { "index": "products" },
  "dest": { "index": "products_v2" }
}

POST /_aliases
{
  "actions": [
    { "remove": { "index": "products", "alias": "products" } },
    { "add": { "index": "products_v2", "alias": "products" } }
  ]
}

10.3 使用索引别名切换 #

bash
POST /_aliases
{
  "actions": [
    { "remove": { "index": "products_v1", "alias": "products" } },
    { "add": { "index": "products_v2", "alias": "products" } }
  ]
}

十一、映射最佳实践 #

11.1 设计原则 #

text
映射设计原则
├── 明确字段类型
│   └── 不要依赖动态映射
├── 合理使用multi-fields
│   └── 同一字段多种用途
├── 控制字段数量
│   └── 避免字段爆炸
├── 使用nested处理数组对象
│   └── 保证查询准确性
└── 合理配置index选项
    └── 不搜索的字段不索引

11.2 性能优化 #

json
{
  "properties": {
    "content": {
      "type": "text",
      "norms": false,
      "index_options": "freqs"
    },
    "status": {
      "type": "keyword",
      "doc_values": true,
      "index": false
    }
  }
}

11.3 存储优化 #

json
{
  "mappings": {
    "_source": {
      "excludes": ["large_field"]
    },
    "properties": {
      "large_field": {
        "type": "text",
        "store": false
      }
    }
  }
}

十二、总结 #

本章介绍了Elasticsearch映射管理:

  1. 动态映射自动推断字段类型
  2. 显式映射提供精确控制
  3. 动态模板实现灵活的类型映射
  4. multi-fields实现一字段多用途
  5. nested解决对象数组独立性问题
  6. 运行时字段提供灵活的计算能力

下一步,我们将学习文档索引操作。

最后更新:2026-03-27