Elasticsearch日期直方图聚合的持续时间

时间:2015-10-15 02:48:11

标签: elasticsearch

我在Elasticsearch中处理的文档的持续时间概念表示为开始和结束时间,例如

{
  issueId: 1,
  issuePriority: 3,
  timeWindow: {
    start: "2015-10-14T17:00:00-07:00",
    end: "2015-10-14T18:00:00-07:00"
  }
},
{
  issueId: 2,
  issuePriority: 1,
  timeWindow: {
    start: "2015-10-14T16:50:00-07:00",
    end: "2015-10-14T17:50:00-07:00"
  }
}

我的目标是生成一个直方图,其中问题的数量及其最大优先级被汇总到15分钟的桶中。因此,对于上面的示例,issue #1将被17:0017:1517:3017:45存储桶中的文字化,不多也不少。

我尝试使用date_histogram聚合,例如:

aggs: {
  max_priority_over_time: {
    date_histogram: {
      field: "timeWindow.start",
      interval: "15minute",
    },
    aggs: {
      max_priority: ${top_hits_aggregation}
    }
  }
}

但显然它只是issue #1桶中的17:00。即使我考虑timeWindow.end,它也只会被添加到18:00桶中。有谁知道如何使用date_histogram或其他Elasticsearch聚合来实现这一目标?潜在地生成从timeWindow.starttimeWindow.end之间15分钟的时间戳范围,以便它们可以正确地进行bucketized。感谢。

3 个答案:

答案 0 :(得分:1)

根据定义,bucketing操作会将查询返回的每个对象放入一个存储桶中,只有一个存储桶,即,您不能让它在一个查询中同时将同一个对象放在多个存储桶中。

如果我正确理解您的问题,那么您需要执行一系列查询,应用range filter来获取每15分钟间隔内的问题数。因此,对于您定义的每个区间,您将获得在该区间内打开的问题:

{
    "query": {
        "filtered": { 
            "filter": {
                "bool": {
                    "must": [
                        "range": {
                            "timeWindow.start" : {
                                "lte" : "2015-10-14T17:00:00-07:00"
                            }
                        },
                        "range": {
                            "timeWindow.end" : {
                                "gte" : "2015-10-14T17:15:00-07:00"
                            }
                        },
                    ]
                }
            }
        }
    }
}

(您需要将max_priority聚合添加到查询中。)

范围查询将由elasticsearch缓存,因此这应该相当有效。假设您的历史数据没有改变,您也可以在应用程序中缓存历史间隔的结果。

答案 1 :(得分:1)

您需要使用脚本。创建一个发出日期数组的脚本。这些日期应从开始日期开始,每个日期应增加15分钟(假设15分钟为间隔)。现在将此脚本放在date_histogram的脚本选项中。 所以基本上脚本应该执行以下操作 -

start=2015-10-14T17:00:00-07:00
end=2015-10-14T18:00:00-07:00"
Output of script = [ "2015-10-14T17:00:00-07:00" , "2015-10-14T17:15:00-07:00" , "2015-10-14T17:30:00-07:00" , "2015-10-14T17:45:00-07:00" ,  "2015-10-14T18:00:00-07:00" ] 

要更多地依靠脚本编写,您可以浏览此Elasticsearch documentations。这些博客可能也很有用 - Thisthisthis

答案 2 :(得分:1)

好的,由于我的数据的时间戳总是被截断到最接近的10分钟,我想我可以使用nested terms aggregation代替:

aggs: {
  per_start_time: {
    terms: {
      field: "timeWindow.start"
    },
    aggs: {
      per_end_time: {
        terms: {
          field: "timeWindow.end"
        },
        aggs: {
          max_priority: ${top_hits_aggregation}
        }
      }
    }
  }
}

这为每个end_time的start_time提供了一个嵌套存储桶,例如:

{
  "key": 1444867800000,
  "key_as_string": "2015-10-15T00:10:00.000Z",
  "doc_count": 11,
  "per_end_time": {
    "doc_count_error_upper_bound": 0,
    "sum_other_doc_count": 0,
    "buckets": [
      {
        "key": 1444871400000,
        "key_as_string": "2015-10-15T01:10:00.000Z",
        "doc_count": 11,
        "max_priority": {
          "hits": {
            "total": 11,
            "max_score": 4,
          }
        }
      }
    ]
  }
}
通过修剪我们后端的桶(ruby on rails),我可以得到以下结果:

[
  {
    "start_time": "2015-10-14 14:40:00 -0700",
    "end_time": "2015-10-14 15:40:00 -0700",
    "max_priority": 4,
    "count": 12
  }
],
[
  {
    "start_time": "2015-10-14 14:50:00 -0700",
    "end_time": "2015-10-14 15:50:00 -0700",
    "max_priority": 4,
    "count": 12
  }
],
...

当然可以在弹性搜索之外进一步映射/缩减为具有任意时间桶的日期直方图。如果timeWindow.starttimeWindow.end和窗口持续时间在时间​​上完全是任意的,我想它相当于只需获取所有内容并在后端进行计数(因为它几乎生成了一个嵌套的时间桶每个文件),幸运的是,我处理的时间戳有些可预测,所以我可以采取这种混合方法。