我目前正在汇总记录,以获取返回记录中字段的平均值(算术平均值)。我的用例要求我掌握几何平均值:
The geometric mean is defined as the nth root of the product of n
我该如何获得这个值(value)?我什至不知道从哪里开始!
谢谢!
最佳答案
这不是小事,但是可以做到的。这个想法是使用日志的总和,然后应用第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}
现在我们可以尝试查询。
ES查询
这是计算几何平均值的查询:
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
及其日志一起插入以提高聚合效率。希望有帮助!
关于elasticsearch - ElasticSearch-如何汇总几何平均值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47657060/