按星期和小时的Elasticsearch聚合

7
我有类型为:

的文档。

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

我希望按星期几统计文档数量。例如,星期一发送了 x 条消息,星期二发送了 y 条消息,以此类推。
我使用了 date_histogram 进行聚合,但它按天返回文档。它确实返回了日期,但是“周三 22 日”和“周三 29 日”被分别作为不同的聚合文档返回。
这与Elasticsearch - group by day of week and hour有些相关,但该问题没有答案,因此我重新发布了它。 根据建议,它要求我在 key_as_string 上进行 term 聚合,但我需要为每个对象添加 doc_count 而不仅仅是计算术语数。我也不知道如何在嵌套聚合中使用 key_as_string。
这是我尝试过的:
"aggs" : {
                "posts_over_days" : {
                    "date_histogram" : { 
                        "field" : "created_time", 
                        "interval": "day",
                        "format": "E" 
                    }
                }

1
你可能想要包含你尝试过的聚合。 - progrrammer
我已经包含了聚合。这与我发布的链接中的答案相同。 - Sambhav Sharma
3个回答

9

以下是我在此回答中的转载:https://dev59.com/JYjca4cB1Zd3GeqPz6qC#31851896

这能帮到你吗:

"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时间”)。
对于小时来说这非常好,但是对于天/月来说,它会给你一个数字而不是月份名称。要解决此问题,可以将时间段作为字符串获取 - 但是,这种方法无法与扩展边界方法一起使用,因此您可能会得到空结果(即[Mon、Tues、Fri、Sun])。
如果需要,可以在此处找到该解决方案:
"aggregations": {
    "dayOfWeek": {
        "terms": {
            "script": "doc['timestamp'].value.getDayOfWeek().getAsText()",
            "order": {
                "_term": "asc"
            }
        }
    }

即使这不能帮助到你,希望其他人可以找到它并从中受益。

1
对于 Elastic 7+,请确保使用 getDayOfWeekEnum()。 - user1306787

5
同样的问题在这个帖子中得到了解决。
为了适应你的问题,我们需要编写一个脚本来将日期转换为每天的小时和星期几。
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)"
            }
        }
    }
}

太棒了..虽然我希望两个东西(小时和天)都有所不同,但现在这很容易了! :) 而且,我正准备从https://dev59.com/aoLba4cB1Zd3GeqPjc3B中获取灵感来回答这个问题。 但是您的脚本完美地运行,没有任何修改。我只需要再花15分钟尝试缩短一点就好了。 非常感谢! - Sambhav Sharma
但要小心脚本,如果数据较少则可以,但如果有10万条数据,则性能会显著下降,您可能只想在结果返回后在应用程序中进行解析。 - progrrammer

2
最简单的方法是定义一个专门的星期几字段,该字段仅包含每个文档的星期几,然后对该字段进行术语聚合
如果出于某种原因您不想这样做(或者无法这样做),那么下面的技巧可能会帮助您获得所需的内容。基本思路是定义一个“date.raw”子字段,该子字段是一个字符串,使用标准分析器进行分析,以便为每个星期几创建术语。然后,您可以在这些术语上进行聚合以获取计数,使用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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接