0

我正在尝试使用 Elasticsearch 计算一些百分比,但我有一个(小)问题。我希望 ES 计算以下内容:“(胜/总)* 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
}

有任何想法吗?

4

1 回答 1

0

我玩了很多,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遍历每个文档,如果status.raw值在win_status中,则win_count会增加,如果它有任何值,则total_count会增加(如果您还想包含空值,则可以删除此条件)
  • combine_script获取每个分片的所有值
  • reduce_script将所有值相加,然后除以。还有一个检查,这样我们就不会被零除,否则脚本会抛出异常。
于 2016-11-04T21:56:17.867 回答