elasticsearch如何解决深度分页

业务控制

elasticsearch默认最多检索10000条数据,对于大说业务来说是不需要一次性展示这么多数据量,比如百度搜索也是控制展示页数,当超过一定页数就不可选择,所以日常项目上可通过增加查询条件,或者默认的筛选条件(仅展示近一个月的数据量,具体多少结合实际的数据增量自行控制),从而减少检索的数据量

修改配置参数

如果前端一定要展示超过10000的数据(有些项目经理会有这种怪癖,认为这是bug…),或者临时改动,可修改 max_result_window 参数,修改命令如下

PUT /index_name/_settings" -d
 ‘{
 “index” : {
 “max_result_window” : 50000
 }
 }’

search after

原理:通过维护一个动态的游标,所谓的动态游标是相对静态游标来说的,后面会有两种游标的解释

第一次查询:
 GET /log/_search
 {
 “size”: 10,
 “query”: {
 “match_all”: {}
 },
 “sort”: [
 {
 “@timestamp”:“desc”
 }
 ]
 }
 第一次结果:
 {
 “took” : 10,
 “timed_out” : false,
 “_shards” : {
 “total” : 1,
 “successful” : 1,
 “skipped” : 0,
 “failed” : 0
 },
 “hits” : {
 “total” : {
 “value” : 229,
 “relation” : “eq”
 },
 “max_score” : null,
 “hits” : [
 {
 “_index” : “log”,
 “_type” : “_doc”,
 “_id” : “Ar2hDIMBG5dCXIr33e0o”,
 “_score” : null,
 “_source” : {
 “@timestamp” : “2022-09-05T15:51:17.936+0800”,
 “message” : “123123123”
 },
 “sort” : [
 1662364277936
 ]
 },…
 第二次查询:
 GET /log/_search
 {
 “size”: 5,
 “query”: {
 “match_all”: {}
 },
“search_after”: [1662364277902 ],
 “sort”: [
 {
 “@timestamp”:“desc”
 }
 ]
 }

以上就是通过search after方式,每次查询传递上次查询结果返回的sort值

scroll

原理:通过维护一个静态游标,每次查询携带scroll_id

第一次查询:
 GET /log/_search?scroll=1m
 {
 “query”: {
 “match_all”: {}
 },
 “sort”: [
 “_doc”
 ],
 “size”: 10
 }
 第一次查询结果:
 {
 “_scroll_id” : “FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFElJU0Jzb01Ca3NoUW5QcElkenVpAAAAAAAAE4sWeWNBWEVhTkFRem1jRHZfSU54ci1YUQ==”,
 “took” : 0,
 “timed_out” : false,
 “_shards” : {
 “total” : 1,
 “successful” : 1,
 “skipped” : 0,
 “failed” : 0
 },
 “hits” : {
 “total” : {
 “value” : 229,
 “relation” : “eq”
 },
 “max_score” : null,
 “hits” : […
 第二次查询:
 GET /_search/scroll
 {
 “scroll”: “10s”,
“scroll_id” : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFElJU0Jzb01Ca3NoUW5QcElkenVpAAAAAAAAE4sWeWNBWEVhTkFRem1jRHZfSU54ci1YUQ"
 }

以上就是通过scroll方式进行查询,每次查询携带scroll_id

总结

以上几种方式是项目中解决深度分页几个常用手段
1,业务的方式以及修改配置参数适用于前端页面显示,其余的方式适用于后台做大数据量处理(比如需要把index的数据同步到另外的index,或者同步到其他数据源,完全是离线操作)
2,性能上面scroll的方式最快,因为第一次调用api时会生成一份版本快照,只会解析一次,后面每次读取都是从快照中读取,不会再进行排名解析,但因为是快照,读取过程中增删数据,感受不到变化,因此它是一种静态游标,当做离线解析数据这种方式为最佳;search after是一种动态解析,也会像scroll一样跳过前多少数据,但是每次都会进行排名解析,有新的数据变化可以感受到,所以说它是一种动态游标
3,需注意,search after和scroll不能跳页读取,比如从访问第1页后,突然想看第5页,这是不允许的,这也是游标的特性,只能按照顺序的访问