Elasticsearch 数据精度丢失
如果字段数据类型设置的为 float 就会出现聚合查询的时候出现精度丢失
测试
例如 设置字段 tmp 类型为 float
{
"took" : 6,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 9,
"relation" : "eq"
},
"max_score" : 2.0,
"hits" : [
{
"_index" : "tests",
"_type" : "_doc",
"_id" : "1595570400000:29.95102.95:3",
"_score" : 2.0,
"_source" : {
"loc" : {
"lat" : "29.95",
"lon" : "102.95"
},
"tmp" : "300.15",
"type" : "TMP"
}
},
{
"_index" : "tests",
"_type" : "_doc",
"_id" : "1595581200000:29.95102.95:3",
"_score" : 2.0,
"_source" : {
"loc" : {
"lat" : "29.95",
"lon" : "102.95"
},
"tmp" : "299.65",
"type" : "TMP"
}
}
]
},
"aggregations" : {
"type" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "tmp",
"doc_count" : 9,
"value" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : 299.6499938964844,
"doc_count" : 1
},
{
"key" : 300.1499938964844,
"doc_count" : 1
}
]
}
}
]
}
}
}
精度丢失
原始的 "tmp" : "299.65" 和查询出来的值 "key" : 299.6499938964844
原始的 "tmp" : "300.15" 和查询出来的值 "key" : 300.1499938964844
查看资料发现是 查询出来的值 将 float 类型转换为了 double类型所以出现了查询出来的值和原始值不一致的情况
验证:
@Test
public void test9() {
float fvalue =299.65f;
BigDecimal bigDecimal = new BigDecimal(fvalue);
System.out.println(bigDecimal.doubleValue());
}
输出结果正好是:299.6499938964844
解决办法
-
如果可以改变 ES 的字段类型 那就最好了 可以设置为 decimal 或者 scaled_float (未做验证 ,请自行验证测试)
-
{ "settings": {}, "mappings": { "doc": { "properties": { "id": { "type": "scaled_float", "scaling_factor": 100 } } } } }
2. 如果数据库已经存放了很多数据的情况下 ,不能去改变字段的数据类 那么可以考虑 将double 进行转换 这样就能得到原始库的值了
@Test
public void test9() {
float fvalue =299.65f;
BigDecimal bigDecimal = new BigDecimal(fvalue);
System.out.println(bigDecimal.doubleValue());
}
输出结果正好是:299.6499938964844