概述
映射官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.17/mapping.html
映射(mapping)是ES中一个很重要的概念,我们知道ES的索引类似于MySQL中的表,而映射就类似于MySQL中的表结构,而文档(Document)就是MySQL表中的一行行数据。
映射(Mapping)的作用是定义文档的结构与数据类型,同时也能设置如何对文档进行索引
映射分为动态映射和显示映射
- 动态映射是只需在ES中添加文档即可自动添加新字段。您可以将字段添加到顶级映射以及内部object 和nested外部字段。
- 显示映射是需要你添加文档前定义好每个字段的数据类型,例如:
- 哪些字符串字段应被视为全文字段
- 哪些字段包含数字、日期或地理位置
- 日期值的 格式
- 自定义规则来控制动态添加字段 的映射
数据类型介绍
官方文档:https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/field-data-types
常见类型
-
binary
- 存储编码为 Base64 字符串的二进制值类型。
-
boolean
- 只包含true和false两个值
-
keyword
- 用于结构化内容,例如 ID、电子邮件地址、主机名、状态代码、邮政编码或标签。使用分词器时不会被分词
-
text
- 用于全文内容(例如电子邮件正文或产品描述)的传统字段类型。适合全文检索
-
date
- 用于存储日期,可使用
format
指定格式化类型
- 用于存储日期,可使用
-
数字
- ES中数字类型有很多种,基本的可参考Java中的数据类型
- byte:一个有符号的 8 位整数,最小值为-128,最大值为127
- short:一个有符号的 16 位整数,最小值为-32,768,最大值为32,767
- integer:一个有符号的 32 位整数,最小值为-231,最大值为231 - 1
- long:一个有符号的 64 位整数,最小值为-263,最大值为263 - 1。
- double:双精度 64 位 IEEE 754 浮点数,限制为有限值。
- float:单精度 32 位 IEEE 754 浮点数,限制为有限值。
- half_float:半精度 16 位 IEEE 754 浮点数,限制为有限值。
- scaled_float:由 支持的浮点数long,按固定double比例因子缩放
- unsigned_long:一个无符号的 64 位整数,最小值为 0,最大值为2^64 - 1
- ES中数字类型有很多种,基本的可参考Java中的数据类型
-
数组
- Elasticsearch 没有专门的array数据类型。默认情况下,任何字段都可以包含零个或多个值,但是,数组中的所有值必须属于相同的数据类型。例如:
- 字符串数组:[ "one", "two"]
- 整数数组:[ 1, 2]
- 数组的数组: [ 1, [ 2, 3]] 相当于 [ 1, 2, 3]
- 对象数组:[ { "name": "Mary", "age": 12 }, { "name": "John", "age": 10 }]
- Elasticsearch 没有专门的array数据类型。默认情况下,任何字段都可以包含零个或多个值,但是,数组中的所有值必须属于相同的数据类型。例如:
-
对象
- JSON 文档本质上是分层的:文档可能包含内部对象,而内部对象本身又可能包含内部对象:
-
IP
- 用于存储IPv4或IPv6地址。
常用的数据类型就是以上几种,如果需要其它的场景,可以参考官方文档
映射的管理
创建映射
静态映射(显示创建)
创建索引时定义映射,控制字段类型和配置:
PUT /my_index
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "1s"
}
// 定义映射
"mappings": {
"properties": {
"title": { "type": "text" },
"price": { "type": "double" },
"tags": { "type": "keyword" },
"created_at": { "type": "date", "format": "yyyy-MM-dd" }
}
}
}
动态映射(自动创建)
当插入文档时,如果字段不存在,ES 会根据数据类型自动创建映射。例如:
PUT /my_index/_doc/1
{
"title": "Elasticsearch Guide",
"price": 49.99,
"tags": ["search", "database"]
}
ES 会自动为字段 title(text+keyword)、price(double)和 tags(keyword)创建映射。
查看映射
-
查看单个索引的映射
GET /my_index/_mapping
-
查看多个索引的映射
GET /index1,index2/_mapping
-
查看所有索引的映射
GET /_mapping
更新映射
新增字段(支持动态更新)
可以向现有映射添加新字段:
PUT /my_index/_mapping
{
"properties": {
"description": { "type": "text" },
"in_stock": { "type": "boolean" }
}
}
修改字段类型(不支持直接修改)
若需修改现有字段类型,需创建新索引并重新索引数据:
// 1. 创建新索引并定义正确的映射
PUT /new_my_index
{
"mappings": {
"properties": {
"price": { "type": "integer" } // 原类型为double,现改为integer
}
}
}
// 2. 使用_reindex API迁移数据
POST /_reindex
{
"source": { "index": "my_index" },
"dest": { "index": "new_my_index" }
}
// 3. 验证数据后删除旧索引
DELETE /my_index
删除映射
-
删除索引(同时删除映射)
DELETE /my_index
-
重置映射(删除后重建)
删除索引后重新创建并定义新映射:DELETE /my_index
PUT /my_index
{
"mappings": { ... } // 新映射定义
}
映射参数详解
核心参数
- type:字段类型(text、keyword、integer 等)
- index:是否索引(true/false)
- analyzer:指定分词器(如 standard、english)
- search_analyzer:搜索时使用的分词器(与 analyzer 不同时生效)
- null_value:替代 null 值的默认值(需与字段类型匹配)
- dynamic:控制动态添加字段的行为(true/false/strict)
高级参数
- copy_to:将字段值复制到目标字段,便于组合搜索
- doc_values:是否存储列式数据(用于聚合和排序,默认 true)
- norms:是否存储归一化因子(影响评分,text 默认 false)
- fields:多字段索引(如同时存储 text 和 keyword 类型)
文档的管理
在 Elasticsearch(ES)中,文档(Document)是可被索引的基本数据单元,以 JSON 格式存储
下面只列举了常用的文档管理的api,如果想要了解其它的可以参考官方文档:https://www.elastic.co/docs/api/doc/elasticsearch/group/endpoint-document
文档的基本概念
- 文档结构:JSON 对象,包含字段和值。
- 唯一性标识:每个文档在索引中需有唯一 ID(可自动生成或手动指定)。
- 元数据字段:
- _index:文档所在的索引名。
- _id:文档的唯一标识符。
- _source:原始 JSON 文档。
- _version:文档版本号,用于乐观锁。
创建文档
指定id创建
PUT /my_index/_doc/1
{
"title": "Getting Started with ES",
"content": "First steps in Elasticsearch",
"user": "john_doe",
"views": 100
}
自动生成id
返回结果包含自动生成的_id。
POST /my_index/_doc
{
"title": "Elasticsearch Tutorial",
"content": "Learn Elasticsearch basics",
"tags": ["search", "database"],
"created_at": "2023-01-01"
}
获取文档
根据 ID 获取单个文档
GET /my_index/_doc/1
检查文档是否存在
HEAD /my_index/_doc/1
获取文档中指定的字段
GET /my_index/_doc/1?_source=filed1,filed2
更新文档
全量更新
PUT /my_index/_doc/1
{
"title": "Updated Title", // 原文档的其他字段会被删除
"views": 101
}
部分更新
POST /my_index/_update/1
{
"doc": {
"views": 102, // 仅更新views字段
"updated_at": "now" // 添加新字段
}
}
删除文档
根据 ID 删除单个文档
DELETE /my_index/_doc/1
基于查询条件删除(需启用 delete-by-query 插件)
POST /my_index/_delete_by_query
{
"query": {
"term": {
"user": "john_doe"
}
}
}
动态映射详解
官方文档:https://www.elastic.co/docs/manage-data/data-store/mapping/dynamic-mapping
动态映射是只需在ES中添加文档即可自动添加新字段。您可以将字段添加到顶级映射以及内部object 和nested外部字段。
验证动态映射
创建一个索引,无需指定映射
PUT dynamic-mapping-01
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "1s"
}
}
添加一个文档
# 请求
PUT dynamic-mapping-01/_doc/1
{
"create_date": "2015/09/02",
"name": "huangsir",
"age": 18,
"addr": "BeiJing",
"ip": "10.0.0.40"
}
查询文档
# 请求
GET dynamic-mapping-01/_doc/1
# 预期返回
{
"_index" : "dynamic-mapping-01", //索引名称
"_type" : "_doc", // 类型
"_id" : "1", // 唯一标识
"_version" : 1, //版本号
// 排序
"_seq_no" : 0,
// 分片
"_primary_term" : 1,
"found" : true,
// 添加的数据
"_source" : {
"create_date" : "2015/09/02",
"name" : "huangsir",
"age" : 18,
"addr" : "BeiJing",
"ip" : "10.0.0.40"
}
}
查看映射
# 请求
GET /dynamic-mapping-01/_mapping
# 预期返回
{
"dynamic-mapping-01" : {
"mappings" : {
"properties" : {
"addr" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"age" : {
"type" : "long"
},
"create_date" : {
"type" : "date",
"format" : "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
},
"ip" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
通过上面的验证,发现其对应的字段的数据类型并不是我们想要的,我们可以指定其数据类型
验证静态映射
官方文档:https://www.elastic.co/docs/manage-data/data-store/mapping/explicit-mapping
静态映射是在创建索引时指定映射的字段、数据类型及其它相关的配置
创建索引
# 请求
PUT explicit-mapping-01
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "1s"
},
"mappings": {
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "byte"
},
"addr": {
"type": "keyword"
},
"ip": {
"type": "ip"
},
"create_date": {
"type": "date",
"format": "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
},
"class": {
"type": "object",
"properties": {
"name":{
"type": "text"
}
}
}
}
}
}
# 预期返回
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "explicit-mapping-01"
}
查看映射
# 请求
GET explicit-mapping-01/_mapping
# 预期返回
{
"explicit-mapping-01" : {
"mappings" : {
"properties" : {
"addr" : {
"type" : "keyword"
},
"age" : {
"type" : "byte"
},
"class" : {
"properties" : {
"name" : {
"type" : "text"
}
}
},
"create_date" : {
"type" : "date",
"format" : "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
},
"ip" : {
"type" : "geo_point"
},
"name" : {
"type" : "text"
}
}
}
}
}
创建文档
# 请求
POST explicit-mapping-01/_doc
{
"create_date": "2015/09/02",
"name": "huangsir",
"age": 18,
"addr": "BeiJing",
"ip": "10.0.0.40",
"class": {
"name": "清华大学"
}
}
# 预期返回
{
"_index" : "explicit-mapping-01",
"_type" : "_doc",
"_id" : "C0JSlpcB-K0y8avWYdSX",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
查看文档
# 请求
GET explicit-mapping-01/_doc/C0JSlpcB-K0y8avWYdSX
# 预期返回
{
"_index" : "explicit-mapping-01",
"_type" : "_doc",
"_id" : "C0JSlpcB-K0y8avWYdSX",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"create_date" : "2015/09/02",
"name" : "huangsir",
"age" : 18,
"addr" : "BeiJing",
"ip" : "10.0.0.40",
"class" : {
"name" : "清华大学"
}
}
}