0%

ES字段类型简介

0x00. 映射

ES虽然不是传统的关系型数据库,但其依然具备字段类型和映射的属性。而映射的主要作用是定义文档(document)中字段的数据类型,决定了数据如何存储和索引。

字段类型可以通过ES动态指定,也可以通过模板指定。通过模板指定后若有新增字段也可以由ES动态指定。

通常在数据比较明确可控的情况下,通过模板来明确指定字段的数据类型,可以优化存储,并且便于进行一些特殊的查询。

0x01. 常用的字段类型

别名类型(Alias field type)

别名字段是为文档中已有的字段创建一个别名。别名可以用于查询、聚合和排序等。但是别名不可用于写入或更新请求。别名的指向字段也不可以是copy_to或多重字段。

别名字段由于不存在于文档原文中,因此在原文字段过滤中不会生效。

在mapping中指定别名字段的方法:

1
2
3
4
"field_name": {
"type": "alias",
"path": "target_name"
}

其中field_name为新的别名字段,而其中的path字段则为目标字段。

数组类型(Arrays)

在ES中不存在一个特定的数组类型的数据类型,在ES中,任意一个字段都可以包含 0个或多个值,但是这些字段都必须是相同类型。

对于列表类型字段不需要提前特别指定。在查询过程中,若是命中列表中其中一个词条,则该文档会被选中。

二进制类型(Binary field type)

二进制类型字段接受使用Base64编码的二进制数据。默认不会被存储也不能进行检索。

在mapping中指定二进制字段的方法:

1
2
3
"field_name": {
"type": "binary"
}

布尔类型(Boolean field type)

布尔类型接受Json中的truefalse值,也接受代表true和false的字符串。

在mapping中指定二进制字段的方法:

1
2
3
"field_name": {
"type": "boolean"
}

日期类型(Date field type)

JSON中没有日期类型,在ES中可以使用几种不同的方式表示:

  • 包含格式化日期的字符串,例如2021-07-18或者2021/07/18 01:17:45
  • 代表毫秒时间戳的数字。
  • 代表秒级时间戳的数字。

在ES内部,日期类型若包含时区则会被转换为一个UTC时区的毫秒时间戳进行储存。对时间类型的查询在内部均会被转换为long类型的范围查询。

在mapping中指定日期字段的方法:

1
2
3
4
"field_name": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}

其中的format字段表示时间格式,可以同时指定多种格式。

地理坐标点类型(Geo-point field type)

地理坐标点类型字段支持经纬度对。可以用于做如下类型的查询:

  • 根据区间、根据到特定点的距离、或多边形查询坐标点。
  • 根据地理信息或到特定点的距离来聚合文档。
  • 将距离信息参与文档评分。
  • 根据距离排序文档。

在mapping中指定二进制字段的方法:

1
2
3
"field_name": {
"type": "geo_point"
}

IP类型(IP field type)

IP字段类型可以用于存储IPv4或IPv6地址。

在mapping中指定IP字段的方法:

1
2
3
"field_name": {
"type": "ip"
}

IP字段可以用IP和子网前缀长度的方式来进行查询。

关键字类型(Keyword type)

通常用于储存结构化数据,例如ID、邮件地址、域名之类的信息。关键字类型不用于全文检索,主要用于排序、聚合和词条查询。

在mapping中指定关键字字段的方法:

1
2
3
"field_name": {
"type": "keyword"
}

数字字段类型映射:

并不是所有的数字字段都应当被映射为数字类型。ES使用数字字段进行range查询。而keyword类型更适合用于词条查询和聚合。对于一个数字字段是否要映射为keyword类型可以从几个角度来考虑:

  • 对这个字段不会使用range查询。
  • keyword类型比数字类型进行term查询时速度更快。

数值类型(Numeric field types)

ES支持如下的数值类型:

  • long、integer、short、byte
  • double、float、half_float、scaled_float
  • unsigned_long

在mapping中指定数值字段的方法:

1
2
3
"field_name": {
"type": "keyword"
}

在选择数值类型的选择上,应该尽可能根据数值范围选择较小的类型,可以加速查询,节约存储空间。

对象类型(Object field type)

ES中支持嵌套对象,在存储和索引时,结构会拍平,因此无需特意指定对象类型。

区间类型(Range field types)

区间类型代表一个上界和下界之间连续的值。可被用于查询和有限的聚合查询。支持直方图聚合以及独立值个数。

在mapping中指定区间字段的方法:

1
2
3
"field_name": {
"type": "integer_range"
}

对于区间类型可以进行term查询,只要查询的值在区间范围内,相应的文档就会被选中。

文本类型(Text field type)

文本类型主要用来索引全文字段,例如电子邮件的全文、产品描述等。内容会被传递给分词器进行分词处理,转换为一系列词条,并用来作为文档的索引。ES通过这些词条可以快速检索到这些全文文档。文本字段不能用于排序和聚合。

在mapping中指定文本类型的方法:

1
2
3
"field_name": {
"type": "text"
}

需要注意的是text类型的字段会被进行分词处理,因此会比较消耗写入性能。如果无需分词查询的字段则应当尽量使用Keyword类型来减少性能消耗。

对于既需要分词处理的又需要聚合的文本字段,可以使用多重字段。

0x02. 小结

ES作为文档数据库使用时,最大的优势是不需要对文档中的字段类型进行提前定义,在文档写入时会自动判断并设置,便于使用。但是这种便利性也会造成性能和资源的损耗。像传统的关系型数据库那样通过模板指定字段类型虽然会些许麻烦,但是在整体写入性能、优化资源占用和查询的效率上会有较大的提升。

请我喝杯奶茶

欢迎关注我的其它发布渠道