【问题标题】:Elasticsearch Aggregation by Day of Week and Hour of DayElasticsearch 聚合按星期几和星期几
【发布时间】:2015-05-13 09:40:21
【问题描述】:

我有以下类型的文件:

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

我想按星期几计算文档数。例如 x 消息在星期一发送,y 消息在星期二发送,以此类推。

我使用 date_histogram 进行聚合,但它会按天返回给我的文档。它确实返回了当天,但说“Wed, 22”和“Wed, 29”作为单独的聚合文档返回。

这与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" 
                    }
                }

【问题讨论】:

  • 您可能希望包含您尝试过的聚合。
  • 我已经包含了聚合。这与我发布的链接中的答案相同。

标签: elasticsearch elasticsearch-plugin spring-data-elasticsearch pyelasticsearch nosql


【解决方案1】:

在这里重新发布我的回答:https://stackoverflow.com/a/31851896/6247

这有帮助吗:

"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')。

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

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

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

即使这对您没有帮助,但希望其他人会发现它并从中受益。

【讨论】:

  • 对于 Elastic 7+,请务必使用 getDayOfWeekEnum()
【解决方案2】:

this thread已经解决了同样的问题。

根据您的问题调整解决方案,我们需要制作一个脚本来将日期转换为一天中的小时和一周中的一天:

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)"
            }
        }
    }
}

【讨论】:

  • 太棒了.. 虽然我想要的东西(小时和天)都不同,但现在这很容易! :) 我正要发布并回答 stackoverflow.com/questions/25492558/… 的见解,但您的脚本无需任何修改即可完美运行。我会再给你 15 分钟的时间来试着缩短一点。非常感谢!
  • 不过要小心脚本,如果数据较少,那没关系,但如果你有 100k 数据,那么它会显着降低性能,你可能只想在你的应用程序中进行解析结果返回后。
【解决方案3】:

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

如果出于某种原因您不想(或不能)这样做,这里有一个技巧可以帮助您获得想要的东西。基本思想是定义一个"date.raw" 子字段,它是一个字符串,使用standard analyzer 进行分析,以便为一周中的每一天创建术语。然后,您可以汇总这些术语以获取计数,使用 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

【讨论】:

    猜你喜欢
    • 2022-08-10
    • 1970-01-01
    • 2020-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-31
    • 2011-10-31
    相关资源
    最近更新 更多