0x00. 映射
ES虽然不是传统的关系型数据库,但其依然具备字段类型和映射的属性。而映射的主要作用是定义文档(document)中字段的数据类型,决定了数据如何存储和索引。
字段类型可以通过ES动态指定,也可以通过模板指定。通过模板指定后若有新增字段也可以由ES动态指定。
通常在数据比较明确可控的情况下,通过模板来明确指定字段的数据类型,可以优化存储,并且便于进行一些特殊的查询。
0x01. 常用的字段类型
别名类型(Alias field type)
别名字段是为文档中已有的字段创建一个别名。别名可以用于查询、聚合和排序等。但是别名不可用于写入或更新请求。别名的指向字段也不可以是copy_to
或多重字段。
别名字段由于不存在于文档原文中,因此在原文字段过滤中不会生效。
在mapping中指定别名字段的方法:
1 | "field_name": { |
其中field_name
为新的别名字段,而其中的path
字段则为目标字段。
数组类型(Arrays)
在ES中不存在一个特定的数组类型的数据类型,在ES中,任意一个字段都可以包含 0个或多个值,但是这些字段都必须是相同类型。
对于列表类型字段不需要提前特别指定。在查询过程中,若是命中列表中其中一个词条,则该文档会被选中。
二进制类型(Binary field type)
二进制类型字段接受使用Base64编码的二进制数据。默认不会被存储也不能进行检索。
在mapping中指定二进制字段的方法:
1 | "field_name": { |
布尔类型(Boolean field type)
布尔类型接受Json中的true
和false
值,也接受代表true和false的字符串。
在mapping中指定二进制字段的方法:
1 | "field_name": { |
日期类型(Date field type)
JSON中没有日期类型,在ES中可以使用几种不同的方式表示:
- 包含格式化日期的字符串,例如
2021-07-18
或者2021/07/18 01:17:45
。 - 代表毫秒时间戳的数字。
- 代表秒级时间戳的数字。
在ES内部,日期类型若包含时区则会被转换为一个UTC时区的毫秒时间戳进行储存。对时间类型的查询在内部均会被转换为long类型的范围查询。
在mapping中指定日期字段的方法:
1 | "field_name": { |
其中的format
字段表示时间格式,可以同时指定多种格式。
地理坐标点类型(Geo-point field type)
地理坐标点类型字段支持经纬度对。可以用于做如下类型的查询:
- 根据区间、根据到特定点的距离、或多边形查询坐标点。
- 根据地理信息或到特定点的距离来聚合文档。
- 将距离信息参与文档评分。
- 根据距离排序文档。
在mapping中指定二进制字段的方法:
1 | "field_name": { |
IP类型(IP field type)
IP字段类型可以用于存储IPv4或IPv6地址。
在mapping中指定IP字段的方法:
1 | "field_name": { |
IP字段可以用IP和子网前缀长度的方式来进行查询。
关键字类型(Keyword type)
通常用于储存结构化数据,例如ID、邮件地址、域名之类的信息。关键字类型不用于全文检索,主要用于排序、聚合和词条查询。
在mapping中指定关键字字段的方法:
1 | "field_name": { |
数字字段类型映射:
并不是所有的数字字段都应当被映射为数字类型。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 | "field_name": { |
在选择数值类型的选择上,应该尽可能根据数值范围选择较小的类型,可以加速查询,节约存储空间。
对象类型(Object field type)
ES中支持嵌套对象,在存储和索引时,结构会拍平,因此无需特意指定对象类型。
区间类型(Range field types)
区间类型代表一个上界和下界之间连续的值。可被用于查询和有限的聚合查询。支持直方图聚合以及独立值个数。
在mapping中指定区间字段的方法:
1 | "field_name": { |
对于区间类型可以进行term查询,只要查询的值在区间范围内,相应的文档就会被选中。
文本类型(Text field type)
文本类型主要用来索引全文字段,例如电子邮件的全文、产品描述等。内容会被传递给分词器进行分词处理,转换为一系列词条,并用来作为文档的索引。ES通过这些词条可以快速检索到这些全文文档。文本字段不能用于排序和聚合。
在mapping中指定文本类型的方法:
1 | "field_name": { |
需要注意的是text类型的字段会被进行分词处理,因此会比较消耗写入性能。如果无需分词查询的字段则应当尽量使用Keyword类型来减少性能消耗。
对于既需要分词处理的又需要聚合的文本字段,可以使用多重字段。
0x02. 小结
ES作为文档数据库使用时,最大的优势是不需要对文档中的字段类型进行提前定义,在文档写入时会自动判断并设置,便于使用。但是这种便利性也会造成性能和资源的损耗。像传统的关系型数据库那样通过模板指定字段类型虽然会些许麻烦,但是在整体写入性能、优化资源占用和查询的效率上会有较大的提升。