这个很棘手。我们假设你有恰恰每个 2 个文档unique taskId
,其中之一将是START
和另一个STOP
。在这种情况下,我们可以执行以下操作:
GET slots/_search
{
"size": 0,
"aggs": {
"by_ids": {
"terms": {
"field": "taskId",
"size": 10000,
"min_doc_count": 2
},
"aggs": {
"start_bucket": {
"filter": {
"term": {
"status.keyword": "START"
}
},
"aggs": {
"datetime_term": {
"max": {
"field": "datetime"
}
}
}
},
"stop_bucket": {
"filter": {
"term": {
"status.keyword": "STOP"
}
},
"aggs": {
"datetime_term": {
"max": {
"field": "datetime"
}
}
}
},
"diff_in_millis": {
"bucket_script": {
"buckets_path": {
"start": "start_bucket.datetime_term",
"stop": "stop_bucket.datetime_term"
},
"script": "return params.stop - params.start"
}
},
"final_sort": {
"bucket_sort": {
"sort": [
{
"diff_in_millis": {
"order": "desc"
}
}
],
"size": 3
}
}
}
}
}
}
As per 这次讨论 https://github.com/elastic/elasticsearch/issues/32153,
需要注意的是,这会对最终的存储桶列表进行排序。因此,如果某个术语不在列表中,则不会对其进行排序。这与对术语 agg 本身进行排序相反,后者会更改列表的内容。
换句话说,我们需要设置顶层size
任意高,这样我们所有的taskIDs
得到聚合。和/或使用仅 2020 年或上个月等的日期过滤器来预过滤上下文,这样我们就可以减少覆盖范围并节省一些 CPU 关键时间。
如果一切顺利并且你的status
has a .keyword
字段(更多关于此here https://www.elastic.co/blog/strings-are-dead-long-live-strings)我们可以进行过滤,您最终会得到您需要的所有信息:
{
...
"aggregations":{
"by_ids":{
"doc_count_error_upper_bound":0,
"sum_other_doc_count":0,
"buckets":[
{
"key":2, <-- taskID (this one was added by myself)
"doc_count":2,
"start_bucket":{
...
},
"stop_bucket":{
...
},
"diff_in_millis":{
"value":3850000.0 <-- duration in millis
}
},
{
"key":1, <-- task from the question
"doc_count":2,
"start_bucket":{
...
},
"stop_bucket":{
...
},
"diff_in_millis":{
"value":250000.0 <-- duration in millis
}
}
]
}
}
}
编辑/更正:
"min_doc_count": 2
是需要的,因为我们只对实际完成的任务感兴趣。如果您想包括那些已运行但尚未完成的任务,请创建另一个赏金任务;)