写点什么

Elasticsearch Mapping parameters(主要参数一览)

作者:Java高工P7
  • 2021 年 11 月 11 日
  • 本文字数:6486 字

    阅读完需:约 21 分钟

PUT my_index


{


"mappings": {


"_doc": {


"properties": {


"first_name": {


"type": "text",


"copy_to": "full_name"


},


"last_name": {


"type": "text",


"copy_to": "full_name"


},


"full_name": {


"type": "text"


}


}


}


}


}


表示字段 full_name 的值来自 first_name + last_name。


关于 copy_to 重点说明:


1、字段的复制是原始值,而不是分词后的词根。


2、复制字段不会包含在_souce 字段中,但可以使用复制字段进行查询。


3、同一个字段可以复制到多个字段,写法如下:“copy_to”: [ “field_1”, “field_2” ]


  • doc_values


当需要对一个字段进行排序时,es 需要提取匹配结果集中的排序字段值集合,然后进行排序。倒排索引的数据结构对检索来说相当高效,但对排序就不那么擅长了。


业界对排序、聚合非常高效的数据存储格式首推列式存储,在 elasticsearch 中,doc_values 就是一种列式存储结构,默认情况下绝大多数数据类型都是开启的,即在索引时会将字段的值(或分词后的词根序列)加入到倒排索引中,同时也会该字段的值加入 doc_values 中,所有该类型的索引下该字段的值用一列存储。


doc_values 的使用示例:


PUT my_index


{


"mappings": {


"_doc": {


"properties": {


"status_code": {


"type": "keyword" // 默认情况下,“doc_values”:true


},


"session_id": {


"type": "keyword",


"doc_values": false


}


}


}


}


}


  • dynamic


是否允许动态的隐式增加字段。在执行 index api 或更新文档 API 时,对于_source 字段中包含一些原先未定义的字段采取的措施,根据 dynamic 的取值,会进行不同的操作:


  1. true,默认值,表示新的字段会加入到类型映射中。

  2. false,新的字段会被忽略,即不会存入_souce 字段中,即不会存储新字段,也无法通过新字段进行查询。

  3. strict,会显示抛出异常,需要新使用 put mapping api 先显示增加字段映射。


dynamic 设置为 false,也是可以通过 put mapping api 进行字段的新增,同样 put mapping api 可以对 dynamic 值进行更新。


举例说明:


PUT my_index/_doc/1


{


"username": "johnsmith",


"name": {


"first": "John",


"last": "Smith"


}


}


PUT my_index/_doc/2 // @1


{


"username": "marywhite",


"email": "mary@white.com",


"name": {


"first": "Mary",


"middle": "Alice",


"last": "White"


}


}


GET my_index/_mapping // @2


代码 @1 在原有的映射下,增加了 username,name.middle 两个字段,通过代码 @2 获取映射 API 可以得知,es 已经为原本不存在的字段自动添加了类型映射定义。


注意:dynamic 只对当前层级具有约束力,例如:


PUT my_index


{


"mappings": {


"_doc": {


"dynamic": false, // @1


"properties": {


"user": { // @2


"properties": {


"name": {


"type": "text"


},


"social_networks": { // @3


"dynamic": true,


"properties": {}


}


}


}


}


}


}


}


代码 @1:_doc 类型的顶层不能不支持动态隐式添加字段映射。


代码 @2:但_doc 的嵌套对象 user 对象,是支持动态隐式添加字段映射。


代码 @3:同样对于嵌套对象 social_networks,也支持动态隐式添加字段映射。


  • enabled


是否建立索引,默认情况下 es 会尝试为你索引所有的字段,但有时候某些类型的字段,无需建立索引,只是用来存储数据即可。只有映射类型(type)和 object 类型的字段可以设置 enabled 属性。示例如下:


PUT my_index


{


"mappings": {


"_doc": {


"properties": {


"user_id": {


"type": "keyword"


},


"last_updated": {


"type": "date"


},


"session_data": {


"enabled": false


}


}


}


}


}


PUT my_index/_doc/session_1


{


"user_id": "kimchy",


"session_data": {


"arbitrary_object": {


"some_array": [ "foo", "bar", { "baz": 2 } ]


}


},


"last_updated": "2015-12-06T18:20:22"


}


上述示例,es 会存储 session_data 对象的数据,但无法通过查询 API 根据 session_data 中的属性进行查询。


同样,可以通过 put mapping api 更新 enabled 属性。


  • eager_global_ordinals


全局序列号,它以字典顺序为每个惟一的术语保持递增的编号。全局序号只支持字符串类型(关键字和文本字段)。在关键字字段中,它们在默认情况下是可用的,但文本字段只能 fielddata=true 时可用。doc_values(和 fielddata)也有序号,是特定段(segment)和字段中所有词根(term)的唯一编号。全局序号只是在此之上构建的,它提供了段序号(segment ordinals)和全局序号(global ordinals)之间的映射,全局序号在整个分片中是唯一的。由于每个字段的全局序号与一个分片(shard)的所有段(segment)相关联,因此当一个新的 segment(段)变为可见时,需要完全重新构建它们。术语聚合依懒全局序号,首先在分片级别(shard)执行聚合,然后汇聚所有分片的结果(reduce)并将全局序号转换为真正的词根(字符串),合并后返回聚合后的结果。默认情况下,全局序号是在搜索时加载的,这对提高索引 API 的速度会非常有利。但是,如果您更加重视搜索性能,,那么在您计划使用的聚合的字段上设置 eager_global_ordinals,会对提高查询效率更有帮助。


eager_global_ordinals 的意思是预先加载全局序号。


其示例如下:


PUT my_index/_mapping/_doc


{


"properties": {


"tags": {


"type": "keyword",


"eager_global_ordinals": true


}


}


}


  • fielddata


为了解决排序与聚合,elasticsearch 提供了 doc_values 属性来支持列式存储,但 doc_values 不支持 text 字段类型。因为 text 字段是需要先分析(分词),会影响 doc_values 列式存储的性能。es 为了支持 text 字段高效排序与聚合,引入了一种新的数据结构(fielddata),使用内存进行存储。默认构建时机为第一次聚合查询、排序操作时构建,主要存储倒排索引中的词根与文档的映射关系,聚合,排序操作在内存中执行。因此 fielddata 需要消耗大量的 JVM 堆内存。一旦 fielddata 加载到内存后,它将永久存在。通常情况下,加载 fielddata 是一个昂贵的操作,故默认情况下,text 字段的字段默认是不开启 fielddata 机制。在使用 fielddata 之前请慎重考虑为什么要开启 fielddata。通常 text 字段用来进行全文搜索,对于聚合、排序字段,建议使用 doc_values 机制。


为了节省内存的使用,es 提供了另一项机制(fielddata_frequency_filter),允许只加载那些词根频率在指定范围(最大,小值)直接的词根与文档的映射关系,最大最小值可以指定为绝对值,例如数字,也可以基于百分比(百分比的计算是基于整个分段(segment),其频率分母不是分段(segment)中所有的文档,而是 segment 中该字段有值的文档)。可以通过 min_segment_size 参数来指定分段中必须包含的最小文档数量来排除小段,也就是说可以控制 fielddata_frequency_filter 的作用范围是包含大于 min_segment_size 的文档数量的段。fielddata_frequency_filter 的使用示例如下:


  • format


在 JSON 文档中,日期表示为字符串。Elasticsearch 使用一组预先配置的格式来识别和解析这些字符串,并将其解析为 long 类型的数值(毫秒)。


日期格式主要包括如下 3 种方式:


1)自定义格式


2)date mesh(已在 DSL 查询 API 中详解)


3)内置格式


1、自定义格式


首先可以使用 java 定义时间的格式,例如:


PUT my_index


{


"mappings": {


"_doc": {


"properties": {


"date": {


"type": "date",


"format": "yyyy-MM-dd HH:mm:ss"


}


}


}


}


}


2、date mesh


某些 API 支持,已在 DSL 查询 API 中详细介绍过,这里不再重复。


3、内置格式


elasticsearch 为我们内置了大量的格式,如下:


  1. epoch_millis


时间戳,单位,毫秒。


  1. epoch_second


时间戳,单位,秒。


  1. date_optional_time


日期必填,时间可选,其支持的格式如下:



  1. basic_date


其格式表达式为 :yyyyMMdd


  1. basic_date_time


其格式表达式为:yyyyMMdd’T’HHmmss.SSSZ


  1. basic_date_time_no_millis


其格式表达式为:yyyyMMdd’T’HHmmssZ


  1. basic_ordinal_date


4 位数的年 + 3 位(day of year),其格式字符串为 yyyyDDD


  1. basic_ordinal_date_time


其格式字符串为 yyyyDDD’T’HHmmss.SSSZ


  1. basic_ordinal_date_time_no_millis


其格式字符串为 yyyyDDD’T’HHmmssZ


  1. basic_time


其格式字符串为 HHmmss.SSSZ


  1. basic_time_no_millis


其格式字符串为 HHmmssZ


  1. basic_t_time


其格式字符串为’T’HHmmss.SSSZ


  1. basic_t_time_no_millis


其格式字符串为’T’HHmmssZ


  1. basic_week_date


其格式字符串为 xxxx’W’wwe,4 为年 ,然后用’W’, 2 位 week of year(所在年里周序号) 1 位 day of week。


  1. basic_week_date_time


其格式字符串为 xxxx’W’wwe’T’HH:mm:ss.SSSZ.


  1. basic_week_date_time_no_millis


其格式字符串为 xxxx’W’wwe’T’HH:mm:ssZ.


  1. date


其格式字符串为 yyyy-MM-dd


  1. date_hour


其格式字符串为 yyyy-MM-dd’T’HH


  1. date_hour_minute


其格式字符串为 yyyy-MM-dd’T’HH:mm


  1. date_hour_minute_second


其格式字符串为 yyyy-MM-dd’T’HH:mm:ss


  1. date_hour_minute_second_fraction


其格式字符串为 yyyy-MM-dd’T’HH:mm:ss.SSS


  1. date_hour_minute_second_millis


其格式字符串为 yyyy-MM-dd’T’HH:mm:ss.SSS


  1. date_time


其格式字符串为 yyyy-MM-dd’T’HH:mm:ss.SSS


  1. date_time_no_millis


其格式字符串为 yyyy-MM-dd’T’HH:mm:ss


  1. hour


其格式字符串为 HH


  1. hour_minute


其格式字符串为 HH:mm


  1. hour_minute_second


其格式字符串为 HH:mm:ss


  1. hour_minute_second_fraction


其格式字符串为 HH:mm:ss.SSS


  1. hour_minute_second_millis


其格式字符串为 HH:mm:ss.SSS


  1. ordinal_date


其格式字符串为 yyyy-DDD,其中 DDD 为 day of year。


  1. ordinal_date_time


其格式字符串为 yyyy-DDD‘T’HH:mm:ss.SSSZZ,其中 DDD 为 day of year。


  1. ordinal_date_time_no_millis


其格式字符串为 yyyy-DDD‘T’HH:mm:ssZZ


  1. time


其格式字符串为 HH:mm:ss.SSSZZ


  1. time_no_millis


其格式字符串为 HH:mm:ssZZ


  1. t_time


其格式字符串为’T’HH:mm:ss.SSSZZ


  1. t_time_no_millis


其格式字符串为’T’HH:mm:ssZZ


  1. week_date


其格式字符串为 xxxx-'W’ww-e,4 位年份,ww 表示 week of year,e 表示 day of week。


  1. week_date_time


其格式字符串为 xxxx-'W’ww-e’T’HH:mm:ss.SSSZZ


  1. week_date_time_no_millis


其格式字符串为 xxxx-'W’ww-e’T’HH:mm:ssZZ


  1. weekyear


其格式字符串为 xxxx


  1. weekyear_week


其格式字符串为 xxxx-'W’ww,其中 ww 为 week of year。


  1. weekyear_week_day


其格式字符串为 xxxx-'W’ww-e,其中 ww 为 week of year,e 为 day of week。


  1. year


其格式字符串为 yyyy


  1. year_month


其格式字符串为 yyyy-MM


  1. year_month_day


其格式字符串为 yyyy-MM-dd


温馨提示,日期格式时,es 建议在上述格式之前加上 strict_前缀。


  • ignore_above


超过 ignore_above 设置的字符串不会被索引或存储。对于字符串数组,将分别对每个数组元素应 ignore_above,超过 ignore_above 的字符串元素将不会被索引或存储。目前测试的结果为:对于字符串字符长度超过 ignore_above 会存储,但不索引(也就是无法根据该值去查询)。其测试效果如下:


public static void create_mapping_ignore_above() { // 创建映射


RestHighLevelClient client = EsClient.getClient();


try {


CreateIndexRequest request = new CreateIndexRequest("mapping_test_ignore_above2");


XContentBuilder mapping = XContentFactory.jsonBuilder()


.startObject()


.startObject("properties")


.startObject("lies")


.field("type", "keyword") // 创建关键字段


.field("ignore_above", 10) // 设置长度不能超过 10


.endO


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


bject()


.endObject()


.endObject();


// request.mapping("user", mapping_user);


request.mapping("_doc", mapping);


System.out.println(client.indices().create(request, RequestOptions.DEFAULT));


} catch (Throwable e) {


e.printStackTrace();


} finally {


EsClient.close(client);


}


}


public static void index_mapping_ignore_above() { // 索引数据


RestHighLevelClient client = EsClient.getClient();


try {


IndexRequest request = new IndexRequest("mapping_test_ignore_above2", "_doc");


Map<String, Object> data = new HashMap<>();


data.put("lies", new String[] {"dingabcdwei","huangsw","wuyanfengamdule"});


request.source(data);


System.out.println(client.index(request, RequestOptions.DEFAULT));


} catch (Throwable e) {


e.printStackTrace();


} finally {


EsClient.close(client);


}


}


public static void search_ignore_above() { // 查询数据


RestHighLevelClient client = EsClient.getClient();


try {


SearchRequest searchRequest = new SearchRequest();


searchRequest.indices("mapping_test_ignore_above2");


SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();


sourceBuilder.query(


// QueryBuilders.matchAllQuery() // @1


// QueryBuilders.termQuery("lies", "dingabcdwei") // @2


// QueryBuilders.termQuery("lies", "huangsw") // @3


);


searchRequest.source(sourceBuilder);


SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);


System.out.println(result);


} catch (Throwable e) {


e.printStackTrace();


} finally {


EsClient.close(client);


}


}


代码 @1:首先查询所有数据,其_souce 字段的值为:"_source":{“lies”:[“dingabcdwei”,“huangsw”,“wuyanfengamdule”]},表名不管字符串的值是否大于 ignore_above 指定的值,都会存储。


代码 @2:用超过 ignore_above 长度的值尝试去搜索,发现无法匹配到记录,表明并未加入到倒排索引中。


代码 @3:用未超过 ignore_above 长度的值尝试去搜索,发现能匹配到记录。


注意:在 es 中,ignore_above 的长度是字符的长度,而 es 其底层实现 lucene 是使用字节进行计算的,故,如果要反馈到 lucnce,请注意关系。


  • ignore_malformed


试图将错误的数据类型索引到字段中,默认情况下会抛出异常,并拒绝整个文档。ignore_malformed 参数,如果设置为真,允许错误被忽略。格式不正确的字段不建立索引,但是文档中的其他字 段正常处理。可以创建索引时,设置 index.mapping.ignore_malformed 配置项来定义索引级别的默认值,其优先级为 字段级、索引级。


  • index


定义字段是否索引,true:代表索引,false 表示不索引(则无法通过该字段进行查询),默认值为 true。


  • index_options


控制文档添加到反向索引的额外内容,其可选择值如下:


  1. docs:文档编号添加到倒排索引。

  2. freqs:文档编号与访问频率。

  3. positions:文档编号、访问频率、词位置(顺序性),proximity 和 phrase queries 需要用到该模式。

  4. offsets:文档编号,词频率,词偏移量(开始和结束位置)和词位置(序号),高亮显示,需要设置为该模式。


默认情况下,被分析的字符串(analyzed string)字段使用 positions,其他字段使用 docs;


  • fields


fields 允许对同一索引中同名的字段进行不同的设置,举例说明:


PUT my_index


{


"mappings": {


"_doc": {


"properties": {


"city": {


"type": "text", // @1


"fields": { // @2


"raw": {


"type": "keyword" // @3


}


}


}


}


}


}


}


@1:上述映射为 city 字段,定义类型为 text,使用全文索引。


@2:为 city 定义多字段,city.raw,其类型用 keyword。


主要就可以用 user 进行全文匹配,也可以用 user.raw 进行聚合、排序等操作。另外一种比较常用的场合是对该字段使用不同的分词器。


  • norms


字段的评分规范,存储该规范信息,会提高查询时的评分计算效率。虽然规范对计分很有用,但它也需要大量磁盘(通常是索引中每个字段的每个文档一个字节的顺序,甚至对于没有这个特定字段的文档也是如此)。从这里也可以看出,norms 适合为过滤或聚合的字段。


注意,可以通过 put mapping api 将 norms=true 更新为 norms=false,但无法从 false 更新到 true。


  • null_value


将显示的 null 值替换为新定义的额值。用如下示例做一个说明:


PUT my_index


{


"mappings": {


"_doc": {


"properties": {


"status_code": {


"type": "keyword",


"null_value": "NULL" // @1


}


}


}


}


}


PUT my_index/_doc/1


{


"status_code": null // @2


}


PUT my_index/_doc/2


{


"status_code": [] // @3


}


GET my_index/_search


{


"query": {


"term": {


"status_code": "NULL" // @4


}


}


}


代码 @1:为 status_code 字段定义“NULL”为空值 null;


代码 @2:该处,存储在 status_code 为 null_value 中定义的值,即"NULL"

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
Elasticsearch Mapping parameters(主要参数一览)