type
status
date
slug
summary
tags
category
icon
password

1、映射介绍

1.1 什么是映射

映射(mapping)类似数据库中的表结构定义 (schema),描述了文档包含哪些字段 ,每个字段的数据类型是什么,以及是如何存储和索引的。官方资料参考
映射可以包含以下内容:
  • 定义Index下的字段名(Field Name)
  • 定义字段的类型,比如数值型、字符串型、布尔型等
  • 定义倒排索引相关的配置,比如是否索引、记录 position 等
我们可以通过以下命令来查看索引的映射
创建映射有两种方式:
  • 动态映射
  • 显式映射

1.2 动态映射(Dynamic mapping)

若向Elasticsearch的索引中添加数据的字段是原先未定义的,数据也依然可以被成功添加。Elasticsearch拥有动态映射机制,会根据添加的数据内容自动识别对应的字段类型并创建索引。支持的数据类型包括:boolean、double、integer、object、array、date。
例如执行下面命令会自动创建索引 user。
查看索引 user 的 mapping 结构。
可以看到 phone 字段被自动映射为 text 类型,并自动增加了 keyword 子字段,说明该文档可以被检索。
动态字段映射的相关参数如下所示:
  • dynamic:开启动态映射的模式。注意已有的字段,是不支持修改 mapping 的,无论 dynamic 配置是什么,这是 Lucene 的特性,倒排索引一旦生成,不支持修改。
    • true:有新字段加入,mapping 也会自动更新
    • false:有新字段加入,mapping 不会被更新,但是新字段会被加入到 _source 元数据中,不过不能被索引查询
    • strict:写入直接失败
  • date_detection:开启日期检测,默认为 true
  • dynamic_date_formats:检测的日期格式,默认为 yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis
  • numeric_detection:开启数值检测,默认为 false
默认映射关系如下:
JSON 类型
Elastic 类型
说明
字符串(包括数字格式)
text
“hello world” --> text ”123” --> text ”123.45” --> text
字符串(日期格式匹配)
date
“2024/02/03” --> date
布尔值
boolean
true or false --> boolean
浮点数
float
123.45 --> double
整数
long (对,不是integer)
123 --> long
对象
Object
数组
由第一个非空数字决定类型
空值 null
忽略
例如在没有新建索引的情况下,插入以下文档数据。
查看索引 user 的 mapping 结构
如果想全局禁止自动创建索引,可以在 elasticsearch.yml 添加下面的配置:

1.3 显式映射(Explicit mapping)

因为被动映射的字段可能不太符合我们的需求,所以我们需要显式映射自定义 mapping 的结构。可以使用下面的语法
例如上面那个例子,我们可以手动创建 user 索引。
这时候查看 user 的索引结构,发现 phone 是 keyword 类型。

1.4 修改映射

映射中已经定义的字段不能被更新和删除,因为 Lucene 实现的倒排索引生成后不允许修改,除非 reindex 更新 mapping。除了下面三种情况:
  • 可以添加新的 filed。
  • 已经存在的 fields 里面可以添加 fields。
  • ignore_above 参数可以更新的。
假如先创建索引 user,包含 userage 两个字段。
然后想增加 address 字段,无论是使用下面哪一种方式,es 都可以识别出 addrees 字段,然后增加到映射。
但是如果想把 age 字段改成 text 类型,就会报错 mapper_parsing_exception

2、映射定义

2.1 映射字段类型

映射字段类型 通过 type 参数配置。Elasticsearch 内置了20多种字段类型用于支持多种多样的结构化数据。

2.1.1 基本类型

  • 字符串类型,包含 text 与 keyword 两种类型。
    • text:文本类型(text)是索引中常用的字段类型,文本类型是一种默认会被分词的字段类型,如果不指定,Elasticsearch会使用标准分词器切分文本,并会把切分后的文本保存到索引中。搜索时,只有搜索文本和索引中的文本相匹配的文档才会出现在搜索结果中。
    • keyword:关键字类型(keyword)的字段与文本类型的字段不同,它用于保存不经过分析、处理的原始文本,实际上keyword类型字段在实际开发中很常用,当需要对文本字段进行精准匹配查询时就必须使用keyword类型字段。
  • 数字类型:long、integer、short、byte、double、float、half_float、scaled_float。
  • boolean 类型:true/false。
  • 日期类型:date 类型,索引中的日期为UTC时间格式,其比北京时间晚8h。另外 json 对象没有日期类型,故 json 中的日期数据会被格式化,具体如下:
    • 字符串类型,例如"2015-01-01"
    • int类型,表示从1970-01-01以来的秒数
    • long类型,表示从1970-01-01以来的毫秒数
  • binary 类型:存储二进制数据,存储之前,需要先用Base64进行编码。该字段类型默认不存储在索引中,也不能用来当搜索条件。
  • range 类型:integer_range、float_range、long_range、double_range、date_range(64-bit 无符号整数,时间戳(单位:毫秒))、ip_range(IPV4 或 IPV6 格式的字符串)

2.1.2 array 类型

数组类型,Elasticsearch 不提供专门的数组类型,使用数组类型时,映射中无须用额外的关键字进行定义。任何字段,都可以包含多个相同类型的数值。

2.1.3 object 类型

对象类型,你可以直接把一个 JSON 对象作为一个字段写入索引,对象里还可以继续嵌套对象。
在插入数据的时候,Elasticsearch 如果检测到数据值是 JSON 对象,会自动转成 object 类型。缺省设置 type 为 object,因此不用显式定义 type。
也可以显示创建 object 类型字段的索引。
Elasticsearch 在存储对象数据时,默认会将原 JSON 文档扁平化处理,上面 JSON 对象变成以下内容。
这种方式导致一个对象不可以作为一个独立的单元来进行检索,这可能会影响搜索结果的准确性,实际中需要使用嵌套对象(nested object)来作为存储对象的容器。可以通过 user.first 的字段名进行查询

2.1.4 nested 类型

嵌套类型可以看成是一个特殊的 object 对象类型,nested 实际上就是 object 的数组,可以让 object 数组独立检索。例如创建一个 user 索引
es 会进行扁平化处理,变成
user.firstuser.last 分别存储多个字段。原来只有两个用户 John SmithAlice White,现在 John 和 Smith 失去了关联,所以下面直接搜索用户名 Alice Smith 也能查询到数据,这就不符合业务预期了。
nested 就是将数组里面的每个 doc 单独变成子文档进行存储,因此在查询时就可以知道具体的结构信息了。要使用 nested 类型必须显示定义映射,否则 es 会自动转成 object 类型

2.1.5 geo 类型

有时开发过程中涉及GIS地图相关的功能,例如与经纬度相关的搜索,这时候就需要用到经纬度类型(geo_point)。你可以创建一个经纬度类型的索引,代码如下。

2.2 重要映射参数

除了 type 参数,和 type 同级的还有以下比较重要的映射参数。
参数
说明
示例
index
是否被索引,设置成false,字段将不会被索引
false
analyzer
指定分词器,分词器在 settings 中定义
ik
boost
增强当前字段的匹配权重
1.23
dynamic
是否开启自动映射,目前支持三个参数:true/false/strict。默认为 true,表示新检测到未定义的的字段时候,自动添加到映射;false 表示不添加到映射;strict 表示当出现未定义的字段,抛出异常并拒绝添加文档
strict
format
自定义日期格式
yyyy-MM-dd
doc_values
对not_analyzed字段,默认都是开启,analyzed字段不能使用,对排序和聚合能提升较大性能,节约内存,如果您确定不需要对字段进行排序或聚合,或者从script访问字段值,则可以禁用doc值以节省磁盘空间
false
fields
可以对一个字段提供多种索引模式,同一个字段的值,一个分词,一个不分词
{"keyword": {"type": "keyword","ignore_above": 256}}
ignore_above
超过长度的字符的文本,将会被忽略,不被索引
100
fielddata
lasticsearch 加载内存 fielddata 的默认行为是延迟加载。 当 Elasticsearch 第一次查询某个字段时,它将会完整加载这个字段所有 Segment 中的倒排索引到内存中,以便于以后的查询能够获取更好的性能。
{"loading" : "eager" }
include_in_all
设置是否此字段包含在 _all 字段中,默认是 true,除非 index 设置成 no 选项
true
index_options
4个可选参数docs(索引文档号) ,freqs(文档号+词频),positions(文档号+词频+位置,通常用来距离查询),offsets(文档号+词频+位置+偏移量,通常被使用在高亮字段)分词字段默认是position,其他的默认是docs
docs
norms
分词字段默认配置,不分词字段:默认{"enable":false},存储长度因子和索引时 boost,建议对需要参与评分字段使用 ,会额外增加内存消耗量
{"enable":true,"loading":"lazy"}
null_value
设置一些缺失字段的初始化值,只有 string 可以使用,分词字段的 null 值也会被分词
NULL
store
是否单独设置此字段的是否存储而从 _source 字段中分离,默认是false,只能搜索,不能获取值
false
search_analyzer
设置搜索时的分词器,默认跟 ananlyzer 是一致的,比如 index 时用 standard+ngram,搜索时用 standard 用来完成自动提示功能
ik
similarity
指定一个字段评分策略,仅仅对字符串型和分词类型有效 ,默认是TF/IDF算法
BM25

2.3 映射元数据

每个文档都会有一些元数据属性,例如
_index_id 这些就被称为文档的元数据,用来描述文档本身的属性。常见的文档元数据有:
  • _index:文档所在的索引,类似于关系型数据库的database。
  • id:文档的id值。
  • _source:文档的原始 json 数据。
  • size:文档 souce 字段的字节长度,需要插件:mapper-size plugin。
  • _ignored:设置为ignore_malformed=true的所有字段。
  • _routing:路由分片字段。
  • _meta:用于用户自定义元数据。

2.4 映射的版本迭代

version
pattern
5.6.x
可手动启用“index.mapping.single_type: true”,使用 join 字段进行替换
6.x
允许索引使用单一类型,有且仅有一个名称,首选_doc 类型;5.x 版本的索引可延续使用,新版本的索引不再支持父/子方式和 join 类型;6.8中需要在索引创建、模板时需要显示指定 include _ type _ name,不显示申明会默认为 name _ doc
7.x
doc 是路径中的永久部分,并且表示的是 endpoint 类型,而不是 doc 类型;include _ type _ name 参数默认为 false;移除 _default mapping 类型
8.x
不再支持特殊类型;移除 include_type_name 参数
Elasticsearch系列:索引配置(Setting)Elasticsearch系列:索引管理
mcbilla
mcbilla
一个普通的干饭人🍚
Announcement
type
status
date
slug
summary
tags
category
icon
password
🎉欢迎来到飙戈的博客🎉
-- 感谢您的支持 ---
👏欢迎学习交流👏