ElasticSearch聚合浮点型丢失精度

zlhcx6iw  于 2023-01-20  发布在  ElasticSearch
关注(0)|答案(1)|浏览(332)

如果您使用Elasticsearch 5.5和动态字段Map并使用双精度值。当我签入Map时,这些值将获得浮点类型。当您使用聚合时,桶中的键将失去精度。值0.62将类似于0.6200000047683716
代码片段

"aggregations": {
    "float_numbers": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": 0.6200000047683716,
          "doc_count": 1
        }
      ]
    }
  }

这里描述了相同的问题。link
我发布这个问题是因为我找到了一个合适的解决方案,我还没有看到,但它帮助了我很大。
解决方法是使浮点数为双精度型。这可以通过动态模板来实现。
动态模板
dynamic field mapping
示例解决方案:
在索引中添加dynamic_templates,还没有项目。

PUT term-test
{
  "mappings": {
    "demo_typ": {
      "dynamic_templates": [
        {
          "all_to_double": {
            "match_mapping_type": "double",
            "mapping": {
              "type": "double"
            }
          }
        }
      ]
    }
  }
}

添加数据

POST term-test/demo_typ
{
  "numeric_field": 0.62,
  "long_filed": 44
}

检查Map

GET term-test/_mapping

执行聚合

GET term-test/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "float_numbers": {
      "terms": {
        "field": "numeric_field"
      }
    }
  }
}
    • 在Java API中,您可以执行以下操作**

1:首先创建索引

elasticClient.admin()
                .indices()
                .prepareCreate(indexName)
                .execute()
                .actionGet();

2:更新Map
JSON语言

{
  "dynamic_templates": [
    {
      "all_to_double": {
        "match_mapping_type": "double",
        "mapping": {
          "type": "double"
        }
      }
    }
  ]
}

我从link获得了代码

public XContentBuilder getXContentBuilderFromJson(final String json) {
        try {
            Map<String, Object> map = new ObjectMapper().readValue(json, new TypeReference<Map<String, Object>>() {});
            return XContentFactory.jsonBuilder().map(map);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

更新Map

elasticClient.admin().indices()
.preparePutMapping(indexName)
.setType(yourType)
.setSource(getXContentBuilderFromJson(json))
.execute()
.actionGet();

3:插入数据

i1icjdpr

i1icjdpr1#

数字会失去精度。这是因为浮点数的工作方式:9.62不能表示为a * 2 ^ b,因此无论是双精度型还是浮点型都不能准确地表示它。
由于浮点型和双精度型不能准确地表示值,因此对它们运行术语聚合通常不是一个好主意。
作为一种解决方法,您可以在聚合之后执行Math.round

相关问题