elasticsearch - 使用嵌套和根级别数据的Elasticsearch嵌套聚合比率

标签 elasticsearch

我有一个简单的聚合感觉。我有一个时序代码如下的文档:

{
  "task_start": "2020-06-03T21:19:07.908821Z",
  "task_end": "2020-06-03T21:27:00.323790Z",
  "sub_tasks": [
    {
      "key": "sub-task1-time-milliseconds",
      "value": 3310
    },
    {
      "key": "sub-task2-time-milliseconds",
      "value": 2410
    },
    ...
  ]
}

嵌套sub_tasks的位置。我想要得到的是每个子任务中的时间与整个任务时间的中值比率。整个任务时间仅为end_time - start_time。我知道如何分别汇总子任务时间和总任务时间。但我想汇总每个文档的比率。

问题在于嵌套聚合,我只能访问带有嵌套数据的数据,而在反向嵌套聚合中,我只能访问根级别的数据,而不能同时访问两者。我知道有一种方法可以使用copy_to,因此我在嵌套路径中拥有任务时间,但是我没有能力修改索引结构,也不希望有额外的存储空间。

这是我尝试过的。对于嵌套聚合:
{
  "aggs": {
    "task_metrics": {
      "nested": {
        "path": "sub_tasks"
      },
      "aggs": {
        "sub_task_metrics": {
          "filter": {
            "term": {
              "sub_tasks.key": "sub-task1-time-milliseconds"
            }
          },
          "aggs": {
            "median_time": {
              "percentiles": {
                "script": {
                  "lang": "painless",
                  "source": """
                            double task_time = (doc['task_end'].value.millis - doc['task_start'].value.millis);
                            return doc['sub_tasks.value'].value / task_time; 
                            """
                },
                "percents": 50
              }
            }
          }
        }
      }
    }
  }
}

但是在该聚合中,doc['task_start']doc['task_end']仅返回零,因为我无权访问它们。为了获得访问权限,我还尝试了添加另一个子聚合的reverse_nested。这使我可以访问doc['task_start']doc['task_end'],但是doc['sub_tasks.value'].value仅返回0

似乎这应该是可能的,但是当我阅读管道聚合和其他脚本聚合时,我不相信任何一个都能满足我的要求。非常感谢您的帮助,谢谢!

最佳答案

这很棘手-已经讨论过here

我认为您将不得不诉诸scripted_metric s和一些方法模拟,因为公开的无痛API是somewhat limited:

{
  "size": 0, 
  "aggs": {
    "task_metrics_median": {
      "scripted_metric": {
        "init_script": "state.ratios = new ArrayList();",

        "map_script": """
          // access the source incl. the nested subtasks
          def d = params._source;

          for (def subtask : d.sub_tasks) {
            // mimicking a `term` query
            if (subtask.key != 'sub-task1-time-milliseconds') break;

            // incoming as strings so parse
            def millis_end = ZonedDateTime.parse(d.task_end).toInstant().toEpochMilli();
            def millis_start = ZonedDateTime.parse(d.task_start).toInstant().toEpochMilli();

            double task_time = (millis_end - millis_start);

            // prevent zero division
            if (task_time <= 0) break;

            state['ratios'].add(subtask.value / task_time);  
          }
        """,

        "combine_script": """
            def ratios = state.ratios;
            Collections.sort(ratios);

            // trivial median calc
            double median;
            if (ratios.length % 2 == 0) {
                median = ((double)ratios[ratios.length/2] + (double)ratios[ratios.length/2 - 1])/2;
            } else {
                median = (double) ratios[ratios.length/2];
            }

            return median
        """,

        "reduce_script": "return states"
      }
    }
  }
}

关于elasticsearch - 使用嵌套和根级别数据的Elasticsearch嵌套聚合比率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62225167/

相关文章:

elasticsearch - Elasticsearch 2.4中数组字段匹配过滤器的不同值

java - Elasticsearch Java API 7.0 批量插入尝试基本示例,抛出错误

elasticsearch - 过滤结果集上的elasticsearch聚合

elasticsearch - 如果原始模式中未定义新的 Elasticsearch 类型,如何不创建它?

search - 在 ElasticSearch 中找到文本的返回字段

node.js - 如何运行elasticsearch-hq?

elasticsearch - Elasticsearch查询聚合仅具有特定模式的术语

elasticsearch - 如何根据日期范围查找某一字段的不同值? Elasticsearch 6.3

elasticsearch - 将旧数据从Elasticsearch存档到Google Cloud Storage

elasticsearch - 在ElasticSearch中按子频率过滤