按星期几和一天中的小时进行 Elasticsearch 聚合

Elasticsearch Aggregation by Day of Week and Hour of Day

我有以下类型的文档:

[{"msg":"hello", date: "some-date"},{"msg":"hi!", date: "some-date"}, ...

我想按星期几计算文档数量。例如,周一发送了 x 条消息,周二发送了 y 条消息,依此类推。

我已经将 date_histogram 与聚合一起使用,但它 return 对我来说是明智的文档。它确实 return 我那天,但是说 "Wed, 22" 和 "Wed, 29" 被 return 编辑为单独的聚合文档。

这与 Elasticsearch - group by day of week and hour 有点相关,但该问题没有答案,所以我重新发布了它。 根据那里的建议,它要求我对 key_as_string 进行术语聚合,但我需要为每个对象添加 doc_count 而不是仅仅计算术语。我也不知道如何在嵌套聚合中使用 key_as_string。

这是我试过的:

"aggs" : {
                "posts_over_days" : {
                    "date_histogram" : { 
                        "field" : "created_time", 
                        "interval": "day",
                        "format": "E" 
                    }
                }

最简单的方法是定义一个专用的星期几字段,它只包含每个文档的星期几,然后在该字段上执行 terms aggregation

如果出于某种原因您不想这样做(或不能这样做),这里有一个 hack 可能会帮助您获得想要的东西。基本思想是定义一个 "date.raw" 子字段,它是一个字符串,使用 standard analyzer so that terms are created for each day of the week. Then you can aggregate on those terms to get your counts, using include 分析以仅包含您想要的术语。

这是我用于测试的映射:

PUT /test_index
{
   "settings": {
      "number_of_shards": 1
   },
   "mappings": {
      "doc": {
         "properties": {
            "msg": {
               "type": "string"
            },
            "date": {
               "type": "date",
               "format": "E, dd MMM yyyy",
               "fields": {
                  "raw": {
                     "type": "string"
                  }
               }
            }
         }
      }
   }
}

和一些示例文档:

POST /test_index/_bulk
{"index":{"_index":"test_index","_type":"doc","_id":1}}
{"msg": "hello","date": "Wed, 11 Mar 2015"}
{"index":{"_index":"test_index","_type":"doc","_id":2}}
{"msg": "hello","date": "Tue, 10 Mar 2015"}
{"index":{"_index":"test_index","_type":"doc","_id":3}}
{"msg": "hello","date": "Mon, 09 Mar 2015"}
{"index":{"_index":"test_index","_type":"doc","_id":4}}
{"msg": "hello","date": "Wed, 04 Mar 2015"}

以及聚合和结果:

POST /test_index/_search?search_type=count
{
    "aggs":{
        "docs_by_day":{
            "terms":{
                "field": "date.raw",
                "include": "mon|tue|wed|thu|fri|sat|sun"
            }
        }
    }
}
...
{
   "took": 2,
   "timed_out": false,
   "_shards": {
      "total": 1,
      "successful": 1,
      "failed": 0
   },
   "hits": {
      "total": 4,
      "max_score": 0,
      "hits": []
   },
   "aggregations": {
      "docs_by_day": {
         "buckets": [
            {
               "key": "wed",
               "doc_count": 2
            },
            {
               "key": "mon",
               "doc_count": 1
            },
            {
               "key": "tue",
               "doc_count": 1
            }
         ]
      }
   }
}

这里是全部代码:

http://sense.qbox.io/gist/0292ddf8a97b2d96bd234b787c7863a4bffb14c5

同类问题已在中解决。

根据您的问题调整解决方案,我们需要编写一个脚本将日期转换为一天中的小时数和星期几:

Date date = new Date(doc['created_time'].value) ; 
java.text.SimpleDateFormat format = new java.text.SimpleDateFormat('EEE, HH');
format.format(date)

并在查询中使用它:

{
    "aggs": {
        "perWeekDay": {
            "terms": {
                "script": "Date date = new Date(doc['created_time'].value) ;java.text.SimpleDateFormat format = new java.text.SimpleDateFormat('EEE, HH');format.format(date)"
            }
        }
    }
}

重新post 从我这里的回答:

这有帮助吗:

"aggregations": {
    "timeslice": {
        "histogram": {
            "script": "doc['timestamp'].value.getHourOfDay()",
            "interval": 1,
            "min_doc_count": 0,
            "extended_bounds": {
                "min": 0,
                "max": 23
            },
            "order": {
                "_key": "desc"
            }
        }
    }

这很好,因为它还会包括结果为零的任何时间,并且它会将结果扩展到涵盖整个 24 小时期间(由于 extended_bounds)。

您可以使用 'getDayOfWeek'、'getHourOfDay'、...(有关更多信息,请参阅 'Joda time')。

这对于小时来说非常有用,但是对于 days/months 它会给你一个数字而不是月份名称。要解决此问题,您可以将时间段作为字符串 - ,这不适用于扩展边界方法,因此您可能得到空结果(即 [Mon, Tues, Fri , 太阳]).

如果你想要它,它就在这里:

"aggregations": {
    "dayOfWeek": {
        "terms": {
            "script": "doc['timestamp'].value.getDayOfWeek().getAsText()",
            "order": {
                "_term": "asc"
            }
        }
    }

即使这对您没有帮助,也希望其他人能找到它并从中受益。