• -------------------------------------------------------------
  • ====================================

date_histogram

elasticsearch dewbay 5年前 (2019-04-12) 2701次浏览 已收录 0个评论 扫描二维码

用法

Date histogram 的用法与 histogram 差不多,只不过区间上支持了日期的表达式。

{"aggs":{    "articles_over_time":{        "date_histogram":{            "field":"date",            "interval":"month"            }        }    }}

interval 字段支持多种关键字:`year`, `quarter`, `month`, `week`, `day`, `hour`, `minute`, `second`

当然也支持对这些关键字进行扩展使用,比如一个半小时可以定义成如下:

{    "aggs":{        "articles_over_time":{            "date_histogram":{                "field":"date",                "interval":"1.5h"                }            }        }}

返回的结果可以通过设置 format 进行格式化:

{    "aggs":{        "articles_over_time":{            "date_histogram":{                "field":"date",                "interval":"1M",                "format":"yyyy-MM-dd"                }            }        }    }

得到的结果如下:

{    "aggregations":{        "articles_over_time":{            "buckets":[{                "key_as_string":"2013-02-02",                "key":1328140800000,                "doc_count":1            },{                "key_as_string":"2013-03-02",                "key":1330646400000,                "doc_count":2            },            ...            ]}        }}

其中 key_as_string 是格式化后的日期,key 显示了是日期时间戳,

time_zone 时区的用法

在 es 中日期支持时区的表示方法,这样就相当于东八区的时间。

{    "aggs":{        "by_day":{            "date_histogram":{                "field":"date",                "interval":"day",                "time_zone":"+08:00"            }        }    }}

offset 使用偏移值,改变时间区间

默认情况是从凌晨 0 点到午夜 24:00,如果想改变时间区间,可以通过下面的方式,设置偏移值:

{"aggs":{    "by_day":{        "date_histogram":{            "field":"date",            "interval":"day",            "offset":"+6h"            }        }    }}

那么桶的区间就改变为:

"aggregations":{    "by_day":{        "buckets":[{            "key_as_string":"2015-09-30T06:00:00.000Z",            "key":1443592800000,            "doc_count":1        },{            "key_as_string":"2015-10-01T06:00:00.000Z",            "key":1443679200000,            "doc_count":1        }]    }}

Missing Value 缺省字段

当遇到没有值的字段,就会按照缺省字段 missing value 来计算:

{    "aggs":{        "publish_date":{            "date_histogram":{                "field":"publish_date",                "interval":"year",                "missing":"2000-01-01"            }        }    }}

其他

对于其他的一些用法,这里就不过多赘述了,比如脚本、Order、min_doc_count 过滤,extended_bounds 等都是支持的。

按时间统计编辑

(测试数据:http://blog.csdn.net/wwd0501/article/details/78501842)如果搜索是在 Elasticsearch 中使用频率最高的,那么构建按时间统计的 date_histogram 紧随其后。 为什么你会想用 date_histogram 呢?

假设你的数据带时间戳。 无论是什么数据(Apache 事件日志、股票买卖交易时间、棒球运动时间)只要带有时间戳都可以进行 date_histogram 分析。当你的数据有时间戳,你总是想在 时间 维度上构建指标分析:

  • 今年每月销售多少台汽车?
  • 这只股票最近 12 小时的价格是多少?
  • 我们网站上周每小时的平均响应延迟时间是多少?

虽然通常的 histogram 都是条形图,但 date_histogram 倾向于转换成线状图以展示时间序列。 许多公司用 Elasticsearch _ 仅仅 _ 只是为了分析时间序列数据。 date_histogram 分析是它们最基本的需要。

date_histogram 与 通常的 histogram 类似。 但不是在代表数值范围的数值字段上构建 buckets,而是在时间范围上构建 buckets。 因此每一个 bucket 都被定义成一个特定的日期大小 (比如, 1 个月 或 2.5 天)。

可以用通常的 histogram 进行时间分析吗?

从技术上来讲,是可以的。 通常的 histogram bucket(桶)是可以处理日期的。 但是它不能自动识别日期。 而用 date_histogram ,你可以指定时间段如 1 个月 ,它能聪明地知道 2 月的天数比 12 月少。 date_histogram 还具有另外一个优势,即能合理地处理时区,这可以使你用客户端的时区进行图标定制,而不是用服务器端时区。

通常的 histogram 会把日期看做是数字,这意味着你必须以微秒为单位指明时间间隔。另外聚合并不知道日历时间间隔,使得它对于日期而言几乎没什么用处。

我们的第一个例子将构建一个简单的折线图来回答如下问题: 每月销售多少台汽车?

GET /cars/transactions/_search
{
   "size" : 0,
   "aggs": {
      "sales": {
         "date_histogram": {
            "field": "sold",
            "interval": "month", 
            "format": "yyyy-MM-dd" 
         }
      }
   }
}
时间间隔要求是日历术语 (如每个 bucket 1 个月)。
我们提供日期格式以便 buckets 的键值便于阅读。

我们的查询只有一个聚合,每月构建一个 bucket。这样我们可以得到每个月销售的汽车数量。 另外还提供了一个额外的 format 参数以便 buckets 有 “好看的” 键值。 然而在内部,日期仍然是被简单表示成数值。这可能会使得 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
            }
         ]
...
}

聚合结果已经完全展示了。正如你所见,我们有代表月份的 buckets,每个月的文档数目,以及美化后的 key_as_string 。

返回空 Buckets编辑

注意到结果末尾处的奇怪之处了吗?

是的,结果没错。 我们的结果少了一些月份! date_histogram (和 histogram 一样)默认只会返回文档数目非零的 buckets。

这意味着你的 histogram 总是返回最少结果。通常,你并不想要这样。对于很多应用,你可能想直接把结果导入到图形库中,而不想做任何后期加工。

事实上,即使 buckets 中没有文档我们也想返回。可以通过设置两个额外参数来实现这种效果:

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

拷贝为 CURL在 SENSE 中查看

这个参数强制返回空 buckets。
这个参数强制返回整年。

这两个参数会强制返回一年中所有月份的结果,而不考虑结果中的文档数目。 min_doc_count 非常容易理解:它强制返回所有 buckets,即使 buckets 可能为空。

extended_bounds 参数需要一点解释。 min_doc_count 参数强制返回空 buckets,但是 Elasticsearch 默认只返回你的数据中最小值和最大值之间的 buckets。

因此如果你的数据只落在了 4 月和 7 月之间,那么你只能得到这些月份的 buckets(可能为空也可能不为空)。因此为了得到全年数据,我们需要告诉 Elasticsearch 我们想要全部 buckets, 即便那些 buckets 可能落在最小日期 之前 或 最大日期 之后 。

extended_bounds 参数正是如此。一旦你加上了这两个设置,你可以把得到的结果轻易地直接插入到你的图形库中,从而得到类似 图 37 “汽车销售时间图” 的图表。

图 37. 汽车销售时间图

date_histogram

Java 代码实现:[java] view plaincopy

  1. /** 
  2.     * Description:按时间统计聚合,用于各种图表数据的聚合 
  3.     * 按时间统计:https://www.elastic.co/guide/cn/elasticsearch/guide/current/_looking_at_time.html 
  4.     * 例: 每月销售多少台汽车 
  5.     *  
  6.     * @author wangweidong 
  7.     * CreateTime: 2017 年 11 月 10 日 上午 10:17:54 
  8.     *  
  9.     * 返回空 buckets 处理:https://www.elastic.co/guide/cn/elasticsearch/guide/current/_returning_empty_buckets.html 
  10.     *  
  11.     * extended_bounds 参数需要一点解释。 min_doc_count 参数强制返回空 buckets,但是 Elasticsearch 默认只返回你的数据中最小值和最大值之间的 buckets。 
  12.         因此如果你的数据只落在了 4 月和 7 月之间,那么你只能得到这些月份的 buckets(可能为空也可能不为空)。 
  13.         因此为了得到全年数据,我们需要告诉 Elasticsearch 我们想要全部 buckets, 即便那些 buckets 可能落在最小日期 之前 或 最大日期 之后 。 
  14.    */  
  15.   @Test  
  16.   public void dataHistogramAggregation() {  
  17.        try {  
  18.            String index = “cars”;  
  19.            String type = “transactions”;  
  20.            SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index).setTypes(type);  
  21.              
  22.            DateHistogramAggregationBuilder field = AggregationBuilders.dateHistogram(“sales”).field(“sold”);  
  23.            field.dateHistogramInterval(DateHistogramInterval.MONTH);  
  24. //         field.dateHistogramInterval(DateHistogramInterval.days(10))  
  25.            field.format(“yyyy-MM”);  
  26.            field.minDocCount(0);//强制返回空 buckets,既空的月份也返回  
  27.            field.extendedBounds(new ExtendedBounds(“2014-01”, “2014-12”));// Elasticsearch 默认只返回你的数据中最小值和最大值之间的 buckets  
  28.              
  29.            searchRequestBuilder.addAggregation(field);  
  30.            searchRequestBuilder.setSize(0);  
  31.            SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();  
  32.              
  33.            System.out.println(searchResponse.toString());  
  34.              
  35.            Histogram histogram = searchResponse.getAggregations().get(“sales”);  
  36.            for (Histogram.Bucket entry : histogram.getBuckets()) {  
  37. //             DateTime key = (DateTime) entry.getKey();   
  38.                String keyAsString = entry.getKeyAsString();   
  39.                Long count = entry.getDocCount(); // Doc count  
  40.                  
  41.                System.out.println(keyAsString + “,销售” + count + “辆”);  
  42.            }  
  43.        } catch (Exception e) {  
  44.             e.printStackTrace();  
  45.        }  
  46.   }  

文章参考:https://www.elastic.co/guide/cn/elasticsearch/guide/current/_looking_at_time.html


露水湾 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:date_histogram
喜欢 (0)
[]
分享 (0)
关于作者:
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址