在我的索引中,我有一些文档,每个文档都带有yyyy-MM-dd'T'HH:mm:ss格式的时间戳(通过'datetime'字段)。

我有一个查询,可为文档中给定字段提供每日(日期直方图)平均值的存储桶,此方法运行良好,没有问题。

我正在尝试将其扩展为过滤每个存储桶,以便日平均仅考虑每天特定时间段内的时间戳记(例如,仅上午或下午创建的文档等)。

我试过以下查询:

{
   "size": 0,
   "aggs": {
      "rating": {
         "date_histogram": {
            "field": "datetime",
            "interval": "1d",
            "time_zone": "Europe/London",
            "min_doc_count": 1
         },
         "aggs": {
            "afternoon": {
               "filter": {
                  "range": {
                     "datetime": {
                        "gte": "12:00:00",
                        "lte": "17:00:00",
                        "format": "HH:mm:ss"
                     }
                  }
               },
               "aggs": {
                  "service": {
                     "avg": {
                        "field": "qr2"
                     }
                  }
               }
            }
         }
      }
   },
   "query": {
      "constant_score": {
         "filter": {
            "range": {
               "datetime": {
                  "gte": "2016-08-28T23:00:00",
                  "lte": "2016-09-29T07:34:49"
               }
            }
         }
      }
   }
}

但这会返回汇总的空值(文档计数为0),即使父级存储桶包含多个时间戳都落在时间范围内的文档,也请参见以下示例:
"aggregations": {
      "rating": {
         "buckets": [
            {
               "key_as_string": "1472428800000",
               "key": 1472425200000,
               "doc_count": 843,
               "afternoon": {
                  "doc_count": 0,
                  "service": {
                     "value": null
                  }
               }
            },
            {
               "key_as_string": "1472515200000",
               "key": 1472511600000,
               "doc_count": 748,
               "afternoon": {
                  "doc_count": 0,
                  "service": {
                     "value": null
                  }
               }
            },

我猜想仅指定datetime的时间部分并没有达到预期的效果,它可能是在将日期部分默认为某个值的情况下进行范围查询,因此与父存储桶中返回的文档的任何时间戳都不匹配。

有什么简单的方法可以做到这一点,还是需要将时间分成一个单独的字段?

任何帮助,不胜感激!

最佳答案

上面的答案很完美。但是对于2.1.0之前的版本,这似乎可行

{
    "script": {
        "script": "def hod = doc.datetime.date.getHourOfDay(); return hod >= min && hod <= max",
        "params": {
            "min": 12,
            "max": 17
        }
    }
}

这是由于较旧版本的问题而已修复。 https://github.com/elastic/elasticsearch-net/issues/1931

09-20 17:08