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,包含
user
和 age
两个字段。然后想增加
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.first
和 user.last
分别存储多个字段。原来只有两个用户 John Smith
和 Alice 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 参数 |
- Author:mcbilla
- URL:http://mcbilla.com/article/56edd18a-9dd2-4d82-a6f1-e11259151210
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts