在我的索引中,我有文档,其中每个文档都有时间戳(通过'datetime'字段),格式为yyyy-MM-dd'T'HH:mm:ss
我有一个查询,它为文档中的给定字段提供每日(日期直方图)平均值的存储桶,这很有效,没有问题。
我正在尝试对此进行扩展以过滤每个存储桶,以便每日平均值仅考虑每天某一部分内的时间戳(例如,仅在早上或下午创建的文档等)。
我尝试过以下查询:
{
"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 doc count),即使父存储桶有多个文档的时间戳落入时间范围 - 请参阅下面的示例:
"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
}
}
},
我猜测只是指定日期时间的时间部分没有达到预期效果,它可能正在进行范围查询,日期部分默认为某个值,因此不匹配父存储桶中返回的文档的任何时间戳
我是否有一种简单的方法可以做到这一点,还是需要将时间分成单独的字段?
非常感谢任何帮助!
答案 0 :(得分:3)
有两种解决方法。
第一个解决方案是索引另一个名为hourOfTheDay
的字段,以便您可以在其上运行简单的数字range
过滤器。
"filter": {
"range": {
"hourOfTheDay": {
"gte": 12,
"lte": 17
}
}
},
第二个解决方案只涉及在script
过滤器
"filter": {
"script": {
"script": {
"inline": "def hod = doc.datetime.date.getHourOfDay(); return hod >= min && hod <= max",
"params": {
"min": 12,
"max": 17
}
}
}
},
对于第二个解决方案,请确保enable dynamic scripting
答案 1 :(得分:1)
上述答案完美无缺。但对于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