一尘不染

如何根据来源匹配在Elasticsearch中获得准确的金额?

elasticsearch

我如何在Elasticsearch中获得确切的总和?前参考我目前正在使用elasticsearch 5.6,我的索引映射如下所示:

{
  "my-index":{
    "mappings":{
      "my-type":{
        "properties":{
          "id":{
            "type":"keyword"
          },
          "fieldA":{
            "type":"double"
          },
          "fieldB":{
            "type":"double"
          },
          "fieldC":{
            "type":"double"
          },
          "version":{
            "type":"long"
          }
        }
      }
    }
  }
}

生成的搜索查询(使用Java客户端)为:

{
 /// ... some filters here
 "aggregations" : {
       "fieldA" : {
         "sum" : {
           "field" : "fieldA"
         }
       },
       "fieldB" : {
         "sum" : {
           "field" : "fieldB"
         }
       },
       "fieldC" : {
         "sum" : {
           "field" : "fieldC"
         }
       }
     }
}

但是,我的结果点击产生以下内容:

{
    "took": 10,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 5,
        "max_score": 3.8466966,
        "hits": [
            {
                "_index": "my-index",
                "_type": "my-type",
                "_id": "25a203b63e264fd2be13db006684b06d",
                "_score": 3.8466966,
                "_source": {
                    "fieldC": 108,
                    "fieldA": 108,
                    "fieldB": 0
                }
            },
            {
                "_index": "my-index",
                "_type": "my-type",
                "_id": "25a203b63e264fd2be13db006684b06d",
                "_score": 3.8466966,
                "_source": {
                    "fieldC": -36,
                    "fieldA": 108,
                    "fieldB": 144
                }
            },
            {
                "_index": "my-index",
                "_type": "my-type",
                "_id": "25a203b63e264fd2be13db006684b06d",
                "_score": 3.8466966,
                "_source": {
                    "fieldC": -7.2,
                    "fieldA": 1.8,
                    "fieldB": 9
                }
            },
            {
                "_index": "my-index",
                "_type": "my-type",
                "_id": "25a203b63e264fd2be13db006684b06d",
                "_score": 3.8466966,
                "_source": {
                    "fieldC": 14.85,
                    "fieldA": 18.9,
                    "fieldB": 4.05
                }
            },
            {
                "_index": "my-index",
                "_type": "my-type",
                "_id": "25a203b63e264fd2be13db006684b06d",
                "_score": 3.8466966,
                "_source": {
                    "fieldC": 36,
                    "fieldA": 36,
                    "fieldB": 0
                }
            }
        ]
    },
    "aggregations": {
        "fieldA": {
            "value": 272.70000000000005
        },
        "fieldB": {
            "value": 157.05
        },
        "fieldC": {
            "value": 115.64999999999999
        }
    }
}

为什么我得到:

115.64999999999999而不是字段C中的115.65 272.70000000000005而不是字段A中的272.7

我应该使用float而不是double?还是有一种方法可以更改查询而无需使用无痛脚本并使用具有指定精度和舍入模式的Java BigDecimal?


阅读 1124

收藏
2020-06-22

共1个答案

一尘不染

这有两种检查方法:

node答:如果安装了node.js,只需在提示符下键入,然后输入所有fieldA值的总和:

 $ node
 108 - 36 - 7.2 + 14.85 + 36
 115.64999999999999            <--- this is the answer

B.打开浏览器的开发人员工具,然后选择“控制台”视图。然后输入与上述相同的和:

 > 108-36-7.2+14.85+36
 < 115.64999999999999

如您所见,这两个结果都与您在ES响应中看到的一致。

规避方法之一就是存储你的号码既可以作为正常的整数(即1485,而不是14.85,3600代替36等)或scaled_floatscalingfactor 100(或更大的取决于精度则需要)

2020-06-22