我目前正在聚合记录以获取返回记录中字段的平均值(算术平均值)。我的用例要求我掌握几何平均值:
几何平均值定义为n
乘积的第n个根
我怎样才能获得这个价值?我甚至不知道从哪里开始!
谢谢!
答案 0 :(得分:1)
这不是微不足道的,但可以做到。想法是使用一个日志总和,然后应用第n个根:
pow(exp((sum of logs)), 1/n)
事实上,GeometricMean的Elasticsearch Index Termlist Plugin聚合就是这样做的。 (但是,这是第三方插件,我无法判断它是否足够稳定。)
假设我们有以下映射:
PUT geom_mean
{
"mappings": {
"nums": {
"properties": {
"x": {
"type": "double"
}
}
}
}
}
我们插入以下文件:
{"x":33}
{"x":324}
{"x":134}
{"x":0.1}
现在我们可以尝试查询。
以下是计算几何平均值的查询:
POST geom_mean/nums/_search
{
"size": 0,
"aggs": {
"aggs_root": {
"terms": {
"script": "'Bazinga!'"
},
"aggs": {
"sum_log_x": {
"sum": {
"script": {
"inline": "Math.log(doc.x.getValue())"
}
}
},
"geom_mean": {
"bucket_script": {
"buckets_path": {
"sum_log_x": "sum_log_x",
"x_cnt": "_count"
},
"script": "Math.pow(Math.exp(params.sum_log_x), 1 / params.x_cnt)"
}
}
}
}
}
}
返回值为:
"aggregations": {
"aggs_root": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Bazinga!",
"doc_count": 4,
"sum_log_x": {
"value": 11.872505784215674
},
"geom_mean": {
"value": 19.455434622111177
}
}
]
}
}
现在有点解释。聚合sum_log_x
计算x
的总和。名为geom_mean
的聚合是sibling pipeline aggregation,它应用于sum_log_x
聚合(其兄弟)的结果。它使用特殊的桶路径_count
来获取元素的数量。 (Here您可以阅读更多关于bucket_script
聚合的内容。)
最后一个技巧是用一些聚合来包装它们,因为,如this issue中所述,bucket_script
不能是顶级聚合。在这里,我对一个始终返回terms
'Bazinga!'
聚合
感谢提出此黑客的anhzhi。
由于几何平均值是通过日志计算的,因此所有x
值都应大于0.但是:
"NaN"
"+Infinity"
,但至少有一个值为0,则结果为"-Infinity"
"+Infinity"
和"-Infinity"
都在值中,则结果为"NaN"
。使用Elasticsearch 5.4测试查询。未测试大量文档的性能,您可以考虑将x
与其日志一起插入,以提高聚合效率。
希望有所帮助!