如何用Python elasticsearch_dsl对脚本字段执行求和操作?
解决Elasticsearch脚本字段聚合求和异常的踩坑记录
我最近在使用Elasticsearch做聚合计算时遇到了一个棘手的问题,折腾了好一阵才找到根源,分享出来帮大家避坑:
初始场景
我先成功运行了这段代码,通过脚本字段为每个文档计算出special值(返回的是double类型):
search = Search(using=client, index='my_index').script_fields( special={'script': { 'source': "<a formula that produces a double>"}} )
查询返回的每个结果里,special字段都正确填充了正值,看起来一切正常。
第一次尝试:直接聚合脚本字段
当我想对所有命中的special字段求和时,直接在搜索语句后追加了sum聚合:
search = Search(using=client, index='my_index').script_fields( special={'script': { 'source': "<a formula that produces a double>"}} ).aggs.metric('total', 'sum', field='special')
结果却让人困惑——返回的聚合结果是{'total': {'value': 0.0}},完全不符合预期。我尝试把metric换成pipeline聚合,结果依然无效。
第二次尝试:将脚本移入聚合
参考论坛思路后,我把计算脚本直接放到了pipeline聚合中:
s=Search(using=client, index='my_index').aggs.pipeline('total', 'sum', script={'source': "<the special formula>"})
这次聚合结果不再是0,但单条测试数据的求和结果和预期值相差了128,还是不对。
最终解决方案:修正字段映射类型
最后在论坛找到问题的核心:字段类型不匹配!虽然我的脚本返回的是double类型,但Elasticsearch索引的映射中,该字段被定义为float类型,聚合计算时默认使用了映射里的float类型进行运算,导致精度异常。
将该字段重新索引为double类型后,聚合求和的结果就完全符合预期了!
内容的提问来源于stack exchange,提问作者rschwieb
相关产品推荐
相关产品推荐

