一、种类

ES的数据类型有很多种,为了提高性能减少存储空间,选择一个足够用的类型就OK了,没必要选择过长的类型。比如各地人口数量,一般用integer存储足够了,没有必要使用long类型。

类型说明
byte8位,-128 ~ 127
short16位,-32768 ~ 32767
integer32位,-231 ~ 231-1
long64位,-263 ~ 263-1
unsigned_long无符号64位整数,0 ~ 264-1
float单精度、32位、符合IEEE 754标准的浮点数
double双精度、64位、符合IEEE 754标准的浮点数
half_float16位半精度IEEE 754浮点类型
scaled_float缩放类型的的浮点数

二、实验

2.1 插入正确的数据

(1)先创建一个新的索引,包含常见的数字类型字段

PUT pigg_test_num
{
  "mappings": {
    "properties": {
      "num_of_byte": {
        "type": "byte"
      },
      "num_of_short": {
        "type": "short"
      },
      "num_of_integer": {
        "type": "integer"
      },
      "num_of_long": {
        "type": "long"
      },
      "num_of_float": {
        "type": "float"
      },
      "num_of_double": {
        "type": "double"
      }
    }
  }
}

(2)插入在字段类型范围内的正确数据

PUT pigg_test_num/_doc/1
{
  "num_of_byte": 127,
  "num_of_short": 32767,
  "num_of_integer": 2147483647,
  "num_of_long": 9223372036854775807,
  "num_of_float": 0.33333,
  "num_of_double": 11111111111111.11111111111111111
}

(3)查看文档的数据

GET pigg_test_num/_search

返回:
{
    "hits":[
        {
            "_index":"pigg_test_num",
            "_type":"_doc",
            "_id":"1",
            "_score":1,
            "_source":{
                "num_of_byte":127,
                "num_of_short":32767,
                "num_of_integer":2147483647,
                "num_of_long":9223372036854776000,
                "num_of_float":0.33333,
                "num_of_double":11111111111111.111
            }
        }
    ]
}

2.2 插入越界的数据

short的最大值是32767

PUT pigg_test_num/_doc/2
{
  "num_of_byte": 127,
  "num_of_short": 32768
}

返回报错
"reason" : "Numeric value (32768) out of range of Java short..."

2.3 给整型赋值浮点数

给long类型赋值浮点数, 虽然能够存储成功,但是已经丢失了精度,所以工作中不能这么用

PUT pigg_test_num/_doc/1
{
  "num_of_long": 9223372036854775807.0001
}
返回
 "_source" : {
    "num_of_long" : 9.223372036854776E18
}

2.4 给整型赋值数字字符串

long类型赋值浮点数字符串, 虽然能够存储成功, 但是存的就是字符串,而不是数字.

PUT pigg_test_num/_doc/1
{
  "num_of_long": "9223372036854775807.0001"
}
返回
"_source" : {
    "num_of_long" : "9223372036854775807.0001"
}

下面验证存的是字符串而不是数字

#期望给long的值加上2
POST pigg_test_num/_update/1
{
  "script": {
    "source": "ctx._source.num_of_long += 2",
    "lang": "painless"
  }
}
# 返回值却是给字符串拼接加上字符"2"
"_source" : {
    "num_of_long" : "9223372036854775807.00012"
}

虽然ES默认对数字类型允许接收字符串,但是并不推荐你这么做,因为如果你只是展示还好,如果要对它进行数学计算(比如上面在script脚本中进行 +=2),这样不会按你的期望执行计算的。所以对数字类型还是传数字而非数字字符串

总结: 综合上面实验, 可以知道工作中还是得传正确格式和范围的数字。

三、重要参数

3.1 coerce

  • coerce参数接受truefalse,默认是true
  • true时,允许数字类型保存数字字符串
  • unsigned_long类型不能设置coerce
coerce优点缺点
true容错高,不会丢失宝贵的客户数据进行数学计算容易踩坑
false严格控制传入的值必须是数字万一上层传的就是数字字符串,保存失败,数据丢失

所以最好的办法是统一给ES写数据的入口,在Java代码层面,就把数据格式校验和转换好。

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "number_one": {
        "type": "integer"
      },
      "number_two": {
        "type": "integer",
        "coerce": false
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "number_one": "10" 	#这个可以保存成功
}

PUT my-index-000001/_doc/2
{
  "number_two": "10" 	#这个保存失败
}

3.2 doc_valuesindex

doc_valuesindex的解释可以参考我之前的博客es mapping参数详解

  • doc_values:为了加快排序、聚合操作,在建立倒排索引的时候,额外增加一个列式存储映射,是一个空间换时间的做法。默认是开启的,对于确定不需要聚合或者排序的字段可以关闭。

  • index设置为false,表明该字段不能被被检索, 不构建倒排索引,如果查询会报错。

数字类型的doc_values默认是true,当你的数字字段确定不需要参与聚合和排序,可以设置为false。
数字类型的index默认是true,当你确定不需要在数字字段上进行term/terms查询,可以设置为false。

如果本文对您有帮助,就给亚瑟王点个赞👍吧

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐