ElasticSearch 2 (31) - 信息聚合系列之时间处理

时间:2024-01-05 08:19:02

ElasticSearch 2 (31) - 信息聚合系列之时间处理

摘要

如果说搜索是 Elasticsearch 里最受欢迎的功能,那么按时间创建直方图一定排在第二位。为什么需要使用时间直方图?

版本

elasticsearch版本: elasticsearch-2.x

内容

如果说搜索是 Elasticsearch 里最受欢迎的功能,那么按时间创建直方图一定排在第二位。为什么需要使用时间直方图?

假设我们的数据都有时间戳,无论我们的数据是 Apache 日志事件,或是股票交易日期,还是棒球赛时间,任何与时间戳有关的数据都可以从时间直方图里得到有价值的信息。通常我们希望根据时间来创建度量:

  • 本年度每月汽车销量是多少?
  • 过去 12 小时股价的变化?
  • 过去一周中网站每小时内的平均响应时延是多少?

普通的直方图通常以条状图表表示,日期直方图则会转换成折线图用来表示时间序列。很多公司使用 Elasticsearch 只为了分析时间序列信息。date_histogram 桶正是我们想要的油条和豆浆。

date_histogram 与一般直方图的工作方式类似,不同的是它没有基于数值字段表示数值区间,而是基于时间范围创建桶。因此,每个桶代表时间轴上的一段(比如:1 月 或 2.5 天)。

普通的直方图可以展示时间吗?

技术上讲是可以的。一个普通的直方图桶可以展示时间,但是它并不没有与日历相关的概念。运用 date_histogram,我们可以指定间隔为 1 月,这样我们可以知道二月比十二月的时间短。date_histogram 还有一个优势就是它可以与时区联用,这让我们可以按照用户所处时区来定制图形

报表,而不是服务器时间。

普通的直方图将时间解释成数字,这意味着我们必须以毫秒为单位指定间隔。这样聚合对日历时间间隔没有任何概念,也无法使用日期信息。

我们第一个示例会创建一个简单的折线图表来回答问题:每个月的汽车销量是多少?

  GET /cars/transactions/_search
{
"size" : 0,
"aggs": {
"sales": {
"date_histogram": {
"field": "sold",
"interval": "month", #1
"format": "yyyy-MM-dd" #2
}
}
}
}

#1 这个间隔是日历语境下的值(例如:每个桶表示一个月)。

#2 为其提供一个时间格式这样能显示的更好看。

我们的查询有单个聚合,每个月创建一个桶,为我们提供每月汽车销售的数量。加上 format 参数可以让桶的键值更“好看”。在内部,日期是以简单数字形式表示的,这会让 UI 设计师感到抓狂,不过,可以通过指定一个通用的日期格式获得更好的格式。

响应返回如预期一样但是有个小意外(看看能否发现它):

  {
...
"aggregations": {
"sales": {
"buckets": [
{
"key_as_string": "2014-01-01",
"key": 1388534400000,
"doc_count": 1
},
{
"key_as_string": "2014-02-01",
"key": 1391212800000,
"doc_count": 1
},
{
"key_as_string": "2014-05-01",
"key": 1398902400000,
"doc_count": 1
},
{
"key_as_string": "2014-07-01",
"key": 1404172800000,
"doc_count": 1
},
{
"key_as_string": "2014-08-01",
"key": 1406851200000,
"doc_count": 1
},
{
"key_as_string": "2014-10-01",
"key": 1412121600000,
"doc_count": 1
},
{
"key_as_string": "2014-11-01",
"key": 1414800000000,
"doc_count": 2
}
]
...
}

聚合被完整的呈现出来,正如看到的,我们有用来表示每个月信息的桶,每月文档的数量信息,以及美化过后的 key_as_string

返回空桶(Returning Empty Buckets)

注意到响应中有什么奇怪的吗?

对,正是这样。我们缺失了一些月份的信息,date_histogram(普通 histogram 也是如此)只返回文档数目非零的那些桶。

这表示直方图以最小形式作为响应结果。通常,这并不是我们想要的行为。在很多应用中,我们希望直接将响应数据传入图形库而不要做任何后续处理。

本质上说,即使数目为零我们也希望桶的信息能出现在结果中,可以设置两个参数来实现这个行为:

  GET /cars/transactions/_search
{
"size" : 0,
"aggs": {
"sales": {
"date_histogram": {
"field": "sold",
"interval": "month",
"format": "yyyy-MM-dd",
"min_doc_count" : 0, #1
"extended_bounds" : { #2
"min" : "2014-01-01",
"max" : "2014-12-31"
}
}
}
}
}

#1 参数强制返回空桶。

#2 参数强制返回全年数据。

两个附加的参数会强制响应返回全年所有月份的信息,无论它们文档数目如何。min_doc_count 哼容易理解:即使桶是空的也会强制作为结果返回。

需要对 extended_bounds 参数做些许解释。 min_doc_count 参数强制空桶信息返回,但是 Elasticsearch 默认只会返回处于最小与最大值之间的数据。

所以如果数据在四月和七月之间,我们的桶只会表示这之间的月份(无论是不是空)。为了得到全年的信息,我们需要告诉 Elasticsearch 我们想要得到那些处于最小值和最大值之外的桶的信息。

extended_bounds 参数就是做这件事情,一旦我们增加了这两个设置,我们就能得到可以直接传入图形库的输出,图形的显示如图 Figure 37, “Cars sold over time”.

Figure 37. Cars sold over time

ElasticSearch 2 (31) - 信息聚合系列之时间处理

示例扩展(Extended Example)

正如无数次见到的那样,可以嵌套使用桶获得更复杂的行为。为了举例说明,我们可以创建一个聚合按季度展示所有汽车品牌总销售额,同时按季度、按每个汽车品牌计算销售总额,这样我们就能知道哪种车型能为我们的生意带来更多收益:

  GET /cars/transactions/_search
{
"size" : 0,
"aggs": {
"sales": {
"date_histogram": {
"field": "sold",
"interval": "quarter", #1
"format": "yyyy-MM-dd",
"min_doc_count" : 0,
"extended_bounds" : {
"min" : "2014-01-01",
"max" : "2014-12-31"
}
},
"aggs": {
"per_make_sum": {
"terms": {
"field": "make"
},
"aggs": {
"sum_price": {
"sum": { "field": "price" } #2
}
}
},
"total_sum": {
"sum": { "field": "price" } #3
}
}
}
}
}

#1 注意我们将间隔从 month 改成了 quarter

#2 按汽车品牌分别求和。

#3 所有汽车品牌总和。

响应返回(结果的少量片段):

  {
....
"aggregations": {
"sales": {
"buckets": [
{
"key_as_string": "2014-01-01",
"key": 1388534400000,
"doc_count": 2,
"total_sum": {
"value": 105000
},
"per_make_sum": {
"buckets": [
{
"key": "bmw",
"doc_count": 1,
"sum_price": {
"value": 80000
}
},
{
"key": "ford",
"doc_count": 1,
"sum_price": {
"value": 25000
}
}
]
}
},
...
}

我们将响应的结果作为图形的输入,展现总售价的折线图,并按季度显示每个汽车品牌的销售总额,如图 Figure 38, “Sales per quarter, with distribution per make”

Figure 38. Sales per quarter, with distribution per make

ElasticSearch 2 (31) - 信息聚合系列之时间处理

有限空间(The Sky’s the Limit)

这些都是显而易见的简单示例,但是要用图表表示聚合总会有所限制。例如,Figure 39, “Kibana—a real time analytics dashboard built with aggregations” 图中呈现了 Kibana 的一个仪表盘里面展示了丰富的合信息。

Figure 39. Kibana—a real time analytics dashboard built with aggregations

ElasticSearch 2 (31) - 信息聚合系列之时间处理

因为聚合的实时性,它们易于查询、处理和交互。这对于非技术员工和分析师来说是理想的工具,因为他们可以分析数据,而知道如何创建 Hadoop 任务。

要创建像 Kibana 这样的强大仪表盘,可能需要理解一些更高级的概念比如:限定范围、过滤以及聚合排序。

参考

elastic.co:

Looking at Time