Elasticsearch max min 等查询 数据精度丢失

探讨了在Elasticsearch中使用float类型字段时遇到的精度丢失问题,通过实例展示了精度丢失的现象,并提供了两种解决方案:一是更改字段类型为decimal或scaled_float;二是使用BigDecimal转换查询结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

image-20200724145952239

解决办法

  1. 如果可以改变 ES 的字段类型 那就最好了 可以设置为 decimal 或者 scaled_float (未做验证 ,请自行验证测试)

  2. {
      "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

image-20200724150243537

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值