字段类型详解
字符串: text, keyword
5.0以后,string类型有重大变更,移除了string类型,string字段被拆分成两种新的数据类型: text用于全文搜索的,而keyword用于关键词搜索。
ElasticSearch字符串将默认被同时映射成text
和keyword
类型,将会自动创建类似下面的动态映射(dynamic mappings
):
{
"message": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
这就是造成部分字段还会自动生成一个与之对应的“keyword”字段的原因。
text
会被分词器解析, 生成倒排索引, 支持模糊、精确查询, 不用于排序, 很少用于聚合(significant text aggregation除外)
常用于全文检索.
如果需要为结构化内容, 比如 id、email、hostnames、状态码、标签等进行索引,则推荐使用 keyword
类型以进行完全匹配. 比如我们需要查询"已发货"的订单, 标记为"已发布"的文章等.
更多信息参考官方文档
PUT my_index
{
"mappings": {
"properties": {
"full_name": {
"type": "text"
}
}
}
}
keyword
不进行分词,直接索引, 支持模糊、精确查询, 支持聚合
PUT my_index
{
"mappings": {
"properties": {
"tags": {
"type": "keyword"
}
}
}
}
ES会对"数值(numeric
)"类型的字段(比如, integet, long)进行优化以支持范围(range)查询. 但是, 不是所有的数值类型的数据都需要使用"数值"类型, 比如产品id, 会员id, ISDN(出版社编号), 这些很少会被进行范围查询, 通常都是精确匹配(term query).
keyword
类型的查询通常比numeric
的要快, 如果不需要范围查询, 则建议使用keyword
类型.
如果不确定使用哪一种, 可以通过multi-field
同时设置keyword
和numeric
类型.
更多信息参考官方文档
数值类型(numeric)
- 整型: byte, short, integer, long 这些与java中的类型一致
- 浮点型: float, half_float, scaled_float, double
类型 | 说明 | 取值范围 |
---|---|---|
byte | 8位有符号整数 | -128 ~ 127 |
short | 16位有符号整数 | -32768 ~ 32767 |
integer | 32位有符号整数 | -2,147,483,648 ~ 2,147,483,647 即:-2^31 ~ 2^32 - 1 |
long | 64位有符号整数 | -2^63 ~ 2^63 - 1 |
float | 32位单精度IEEE 754浮点类型, 有限值, 24bits | 2^-149 ~ (2 - 2^-23) · 2^127 |
double | 64位双精度IEEE 754浮点类型, 有限值, 53bits | 2^-1074 ~ (2 - 2^-52) · 2^1023 |
half_float | 16位半精度IEEE 754浮点类型, 有限值, 11bits | 2^-24 ~ 65504 |
scaled_float | 带有缩放因子scaling_factor的浮点数, 可以当整型看待 |
比如:
PUT my_index
{
"mappings": {
"properties": {
"number_of_bytes": {
"type": "integer"
},
"time_in_seconds": {
"type": "float"
},
"price": {
"type": "scaled_float",
"scaling_factor": 100
}
}
}
}
上面我们定义了3个字段:
- number_of_bytes: 整型, integer
- time_in_seconds: 浮点型, float
- price: 带有缩放因子scaling_factor的浮点数. 比如价格是99.99, 缩放因子为100, 那么存储的值就是9999. 这种方式我们在数据库中也经常使用, 比如我们在mysql中存储价格, 只需要精确到分的话, 我们可以使用
decimal(12,2)
或者int
类型, 使用int类型可以节省空间而且不存在精度转换问题, 但是我们必须在业务逻辑中使用缩放因子进行转换, 而ES的scaled_float直接帮我们处理了.
对于上面展示的3种浮点类型(float
, half_float
, scaled_float
)来说, -0.00
和+0.00
是不同的值,使用term
查询-0.00
时不会匹配+0.00
, 反之亦然。对于范围查询(range query)来说也是如此:如果上边界是-0.00
则无法匹配+0.00
,如果下边界是+0.00
则不会匹配-0.00
数值类型使用的注意事项:
- 在满足业务需求的情况下, 尽量选择范围小的类型, 这与mysql等关系型数据库的设计要求是一致的. 字段占用的空间越小, 搜索和索引的效率越高(这个有点废话, 数据量越小肯定越快了).
官方文档说"storage is optimized based on the actual values that are stored", 难道一个integer类型的字段在存储很小的值, 比如100, 的时候会只占用1个字节而不是4个字节吗? 这个与mysql倒是不同的. 在mysql的存储中int就是4个字节, 而varchar才会根据实际的内容占用空间并记录长度.
- 如果是浮点数, 则也要优先考虑使用scaled_float类型.
如果我们存储商品价格只需要精确到分, 两位小数点, 把缩放因子设置为100, 那么浮点价格99.99存储时使用的是integer 类型, 占用空间比float类型更小.
scaled_float在查询时的的数据处理应该与mysql类似, 比如: SELECT * FROM products WHERE price > 99.99 * 100, 而不是 SELECT * FROM products WHERE price / 100 > 99.99, 后面一个写法不符合mysql优化原则: 不要对栏位进行函数运算以及类型转换.
未完待续....