我试图用Elasticsearch计算一些百分比,但我有一个(小)问题。我想让ES计算以下内容:"(wins/Total) * 100".
所以我加了:
"bucket_script": {
"buckets_paths": {
"total": "TotalStatus",
"wins": "TotalWins"
},
"script": " (total/ wins) * 100"
}
到我的ES请求,它看起来像:
{
"size": 0,
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "*",
"analyze_wildcard": true
}
}
],
"must_not": []
}
},
"aggs": {
"status": {
"terms": {
"field": "status.raw"
}
},
"wins": {
"terms": {
"field": "status.raw",
"include": {
"pattern": "Accepted|Released|Closed"
}
}
},
"losses": {
"terms": {
"field": "status.raw",
"include": {
"pattern": "Rejected"
}
}
},
"TotalStatus": {
"sum_bucket": {
"buckets_path": "status._count"
}
},
"TotalWins": {
"sum_bucket": {
"buckets_path": "wins._count"
}
},
"TotalLosses": {
"sum_bucket": {
"buckets_path": "losses._count"
}
}
}
}
返回以下错误:
{
"error": {
"root_cause": [
{
"type": "parsing_exception",
"reason": "Could not find aggregator type [buckets_paths] in [bucket_script]",
"line": 54,
"col": 28
}
],
"type": "parsing_exception",
"reason": "Could not find aggregator type [buckets_paths] in [bucket_script]",
"line": 54,
"col": 28
},
"status": 400
}
知道的吗?
我玩了很多bucket_script
,但我想这可能是不可能的,因为它不能是顶级聚合,你也需要total_wins和total_status来自同一个父聚合与一个数值,我认为这可能是不可能的。
但它可以通过脚本度量聚合来解决
{
"size": 0,
"aggs": {
"win_loss_ratio": {
"scripted_metric": {
"init_script": "_agg['win_count'] = 0; _agg['total_count'] = 0; _agg['win_status']=['Accepted','Released','Closed'];",
"map_script": "if (doc['status.raw'].value in _agg['win_status']) { _agg['win_count']+=1};if (doc['status.raw'].value) { _agg['total_count']+=1}",
"combine_script": "return [_agg['win_count'],_agg['total_count']];",
"reduce_script": "total_win = 0; total_status_count=0; for (a in _aggs) { total_win += a[0]; total_status_count += a[1] }; if(total_win == 0) {return 0} else {return (total_status_count/total_win) * 100}"
}
}
}
}
- init_script初始化三个变量。win_status数组包含所有与win状态对应的值。
- map_script遍历每个文档,如果状态。raw value在win_status中,则win_count递增,如果它有任何值,则total_count递增(如果您还想包含空值,可以删除此if条件)
- combine_script获取每个分片的所有值
- reduce_script将所有值求和然后除。还有一个检查,这样我们就不会除以零,否则脚本会抛出异常。