ELK-20180411-我竟不知道 mappings 的重要性

Problem

# 纯小数计算 avg,结果不正确
curl -XGET http://ES_URL:9200/ES_INDEX/ES_TYPE/_search -d '
  {
    "query": {
      "bool": {
        "must": [
          {
            "query_string": {
              "query": "xxx",
              "analyze_wildcard": true
            }
          },
          {
            "range": {
              "orig_timestamp": {
                "gte": "2018-04-11T10:11:35+08:00",
                "lte": "2018-04-11T15:11:35+08:00"
              }
            }
          }
        ],
        "must_not": []
      }
    },
    "sort": [
      {
        "orig_timestamp": "asc"
      }
    ],
    "aggs": {
      "time": {
        "date_histogram": {
          "field": "orig_timestamp",
          "interval": "1h",
          "time_zone": "Asia/Shanghai",
          "min_doc_count": 3
        },
        "aggs": {
          "success_rate": {
            "stats": {
              "field": "hourly_success_rate"
            }
          }
        }
      },
      "error_rate": {
        "stats": {
          "field": "hourly_error_rate"
        }
      }
    },
    "timeout": "300s",
    "size": 30
  }'

然后 aggs 中 sum/avg/stats 对纯小数取出的计算结果总是做了取整计算。
问题大概同 aggs的sum 求和后数值只有整数部分,小数部分都没了

Solution

其实是因为 mappings,利用如下命令可以看到 mappings 信息。

curl -XGET http://ES_URL:9200/ES_INDEX/_mappings
{
	"ES_INDEX": {
		"mappings": {
			"ES_TYPE": {
				"properties": {
					"hourly_error_rate": {
						"type": "long"
					},
					"hourly_success_rate": {
						"type": "long"
					}
				}
			}
		}
	}
}

结果,可以看到这个纯小数所在的字段 field 的映射类型 type 是 long 长整型。
假设第一个塞进该字段的数是 1,那么他映射为 long 长整型,然后即便之后塞进去的数字都是 float 浮点数类型,但是取出来做 avg 的时候,它内部应该是先拿到 mappings,根据 mapping 定义临时变量,然后计算。那么,0.5 变成 long 型,就取整成了 0。假设原来需要计算 (0.19+0.51+1)/3,那么就变成了 (0+0+1)/3=0.33333,悲剧就是这么产生的。

想要规避这个问题,纯靠保持第一个录入的数据正确还是不太保险。最好是自己写 create index 之后加入 mappings 信息,或者用 template 也可以。
总之就是最保险的方案就是需要提前定义字段映射信息,保证 index 的映射元数据是正确的。

Reference

Incorrect sum while aggregating in elasticsearch for one particular index

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值