前言
使用elasticsearch查询分页时遇到需要先对某个条件聚合后再取每个桶中的第一条记录的情况,请教了下同事,再自身研究了一些时间才搞出来,特做此记录,希望也能帮到大家吧~ ~
这里用的elasticsearch版本是6.4.3。这里使用elasticsearch-head搞几条数据做测试例子…
概念及作用
bucket(桶)
简单来说就是满足特定条件的文档的集合
max
用于跟踪并返回从聚集的文档中提取的数值中的最大值
bucket_sort
bucket_sort聚合与所有管道聚合一样,在所有其他非管道聚合之后执行。这意味着排序只适用于已经从父聚合返回的任何bucket。
sort
根据字段排序
一、首先添加5条测试数据
索引:test,type:person
{
"mappings": {
"person": {
"properties": {
"name": {
"type": "text"
},
"logTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss||epoch_millis"
},
"groupTime": {
"type": "keyword"
}
}
}
}
}
二、复合查询请求
{
"from": 0,
"size": 0,
"query": {
"bool": {}
},
"aggregations": {
"groupTime": {
"terms": {
"field": "groupTime",
"size": 2147483647,
"min_doc_count": 1,
"shard_min_doc_count": 0,
"show_term_doc_count_error": false,
"order": [
{
"_count": "desc"
},
{
"_key": "desc"
}
]
},
"aggregations": {
"sortTime": {
"max": {
"field": "logTime"
}
},
"groupTime": {
"top_hits": {
"from": 0,
"size": 1,
"version": false,
"explain": false,
"_source": {
"includes": [
"name",
"logTime",
"groupTime"
],
"excludes": []
},
"sort": [
{
"logTime": {
"order": "desc"
}
}
]
}
},
"default_sort": {
"bucket_sort": {
"sort": [
{
"sortTime": {
"order": "desc"
}
}
],
"from": 0,
"gap_policy": "SKIP"
}
}
}
}
}
}
三、请求结果
可以看出根据groupTime分组并根据logTime倒序,结果得出两条数据,并且各自取分组中时间最大的那一条数据
四、注意事项
需要注意的是,我groupTime设置为text字段时貌似聚合有问题,keyword类型字段没问题,所以groupTime字段设置为了keyword类型(其它类型没做尝试)。
这个也是我尝试多次后能得到我需要的结果的语句(本人也是个elasticsearch小白,不能说自己说的就对,只能大概说说我自己的理解)。
max会取桶中最大的值,而我需要的是不是一个值而是最大的值所在的那条记录的部分字段,所以先用sort倒序排序,然后采用max取到了桶中第一条记录,最后根据bucket_sort给得出的所有记录排序。