1、Elasticsearch支持聚合后分页吗,为什么?
不支持,看看Elasticsearch员工如何解读。
1)性能角度——聚合分页会在大量的记录中产生性能问题。
2)正确性角度——聚合的文档计数不准确。
所以奇怪的事情可能会发生,如第二页的第一项具有比第一页的最后一个元素更高的计数。
2、Elasticsearch要实现聚合后分页,该怎么办?
方案:需要展示满足条件的全部数据条数,即需要全量聚合,且按照某规则排序。
注意,如果你要聚合的数据量很大(十万、百万甚至千万级),这必然会很慢并且可能超时。
步骤1:全量聚合,size设置为最大值: 2147483647。
ES5.X/6.X版本设置为2147483647 ,它等于2^31-1,
是32位操作系统中最大的符号型整型常量;ES1.X 2.X版本设置为0。
例如:
"aggregations": {
"statistics_assets": {
"terms": {
"field": "one_account.one_account_no",
"size": 2147483647,
"order": {
"assets": "asc"
}
},
"aggregations": {
"assets": {
"sum": {
"field": "assets.merge"
}
}
}
}
}
上面size设置为了最大值2147483647,因为聚合的结果只有几百或者几千(如果聚合的结果很多不能一次性返回考虑使用bucket_sort,下面会说到),我们聚合结果可以一次性返回后,可通过分页参数获取指定部分结果(Java可用list或LinkedHashMap存储,HashMap存入顺序可能会改变)
步骤2:将聚合结果存入内存中,使用Java可以考虑list或map存储。
步骤3:内存内分页,Java里对list中存储的数据进行分页返回行。
如每页10条数据,取第一页就是:取list中第0到第9个元素,以此类推。
总结:
这篇文章讲的方法是聚合数据量不大且聚合结果不是很多时,将聚合结果全部返回,然后java后端用list存储并分页。
缺点:
但是这个方法如果数据量过大,在es聚合的时候会超时也会很慢,并且如果产生的聚合结果很多的话一次性返回给java端也不行。如果你的聚合数据量不大,又不想将聚合的结果一次性返回,可以考虑采用bucket_sort,
例如:
"aggregations": {
"statistics_assets": {
"terms": {
"field": "one_account.one_account_no",
"size": 245645500
},
"aggregations": {
"assets": {
"sum": {
"field": "assets.merge"
}
},
"assets_bucket_sort": {
"bucket_sort": {
"sort": {
"assets": {
"order": "desc"
}
},
"from": 0,
"size": 10
}
}
}
}
}
参考如下官方文档或文章:
Bucket sort aggregationedit
How to add Bucket Sort to Query Aggregation
Aggregation + sorting +pagination in elastic search
如果你的聚合数据量很大,使用bucket_sort也不行的话,建议让中台或数据部门es新加字段,数据重新进行处理计算,把要聚合的数据弄到新加的字段里,这样你就不用聚合了,只需要直接取该字段的值就行。
参考文章:
Elasticsearch聚合后分页深入详解