Elasticsearch 分页查询
前言
我们在实际工作中,有很多分页的需求,商品分页、订单分页等,在MySQL中我们可以使用limit,那么在Elasticsearch中我们可以使用什么呢?
ES 分页搜索一般有三种方案,from + size、search after、scroll api,这三种方案分别有自己的优缺点,下面将进行分别介绍。
使用的数据是kibana中的kibana_sample_data_flights。
from + size
这是ES分页中最常用的一种方式,与MySQL类似,from指定起始位置,size指定返回的文档数。
GET kibana_sample_data_flights/_search
{
"from": 10,
"size": 2,
"query": {
"match": {
"DestWeather": "Sunny"
}
},
"sort": [
{
"timestamp": {
"order": "asc"
}
}
]
}
这个例子中查询航班中,目的地的天气是晴朗的,并且按时间进行排序。
使用简单,且默认的深度分页限制是1万,from + size 大于 10000会报错,可以通过index.max_result_window参数进行修改。
{
"error": {
"root_cause": [
{
"type": "query_phase_execution_exception",
"reason": "Result window is too large, from + size must be less than or equal to: [10000] but was [10001]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting."
}
],
"type": "search_phase_execution_exception",
"reason": "all shards failed",
"phase": "query",
"grouped": true,
"failed_shards": [
{
"shard": 0,
"index": "kibana_sample_data_flights",
"node": "YRQNOSQqS-GgSo1TSzlC8A",
"reason": {
"type": "query_phase_execution_exception",
"reason": "Result window is too large, from + size must be less than or equal to: [10000] but was [10001]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting."
}
}
]
},
"status": 500
}
这种分页方式,在分布式的环境下的深度分页是有性能问题的,一般不建议用这种方式做深度分页,可以用下面将要介绍的两种方式。
理解为什么深度分页是有问题的,我们可以假设在一个有 5 个主分片的索引中搜索。 当我们请求结果的第一页(结果从 1 到 10 ),每一个分片产生前 10 的结果,并且返回给协调节点 ,协调节点对 50 个结果排序得到全部结果的前 10 个。
现在假设我们请求第 1000 页,结果从 10001 到 10010 。所有都以相同的方式工作除了每个分片不得不产生前10010个结果以外。 然后协调节点对全部 50050 个结果排序最后丢弃掉这些结果中的 50040 个结果。
可以看到,在分布式系统中,对结果排序的成本随分页的深度成指数上升。
search after
search after 利用实时有游标来帮我们解决实时滚动的问题。第一次搜索时需要指定 sort,并且保证值是唯一的,可以通过加入 _id 保证唯一性。
GET kibana_sample_data_flights/_search
{
"size": 2,
"query": {
"match": {
"DestWeather": "Sunny"
}
},
"sort": [
{
"timestamp": {
"order": "asc"
},
"_id": {
"order": "desc"
}
}
]
}
在返回的结果中,最后一个文档有类似下面的数据,由于我们排序用的是两个字段,返回的是两个值。
"sort" : [
1614561419000,
"6FxZJXgBE6QbUWetnarH"
]
第二次搜索,带上这个sort的信息即可,如下
GET kibana_sample_data_flights/_search
{
"size": 2,
"query": {
"match": {
"DestWeather": "Sunny"
}
},
"sort": [
{
"timestamp": {
"order": "asc"
},
"_id": {
"order": "desc"
}
}
],
"search_after": [
1614561419000,
"6FxZJXgBE6QbUWetnarH"
]
}
scroll api
创建一个快照,有新的数据写入以后,无法被查到。每次查询后,输入上一次的 scroll_id。目前官方已经不推荐使用这个API了,使用search_after即可。
GET kibana_sample_data_flights/_search?scroll=1m
{
"size": 2,
"query": {
"match": {
"DestWeather": "Sunny"
}
},
"sort": [
{
"timestamp": {
"order": "asc"
},
"_id": {
"order": "desc"
}
}
]
}
在返回的数据中,有一个_scroll_id字段,下次搜索的时候带上这个数据,并且使用下面的查询语句。
POST _search/scroll
{
"scroll" : "1m",
"scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAA6UWWVJRTk9TUXFTLUdnU28xVFN6bEM4QQ=="
}
上面的scroll指定搜索上下文保留的时间,1m代表1分钟,还有其他时间可以选择,有d、h、m、s等,分别代表天、时、分钟、秒。
搜索上下文有过期自动删除,但如果自己知道什么时候该删,可以自己手动删除,减少资源占用。
DELETE /_search/scroll
{
"scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAA6UWWVJRTk9TUXFTLUdnU28xVFN6bEM4QQ=="
}
总结
from + size 的优点是简单,缺点是在深度分页的场景下系统开销比较大。
search after 可以实时高效的进行分页查询,但是它只能做下一页这样的查询场景,不能随机的指定页数查询。
scroll api 方案也很高效,但是它基于快照,不能用在实时性高的业务场景,且官方已不建议使用。
参考资料
- https://www.elastic.co/guide/cn/elasticsearch/guide/2.x/pagination.html
- https://www.elastic.co/guide/en/elasticsearch/reference/7.11/paginate-search-results.html
Elasticsearch 分页查询的更多相关文章
- elasticsearch 分页查询实现方案——Top K+归并排序
elasticsearch 分页查询实现方案 1. from+size 实现分页 from表示从第几行开始,size表示查询多少条文档.from默认为0,size默认为10,注意:size的大小不能超 ...
- Elasticsearch——分页查询From&Size VS scroll
Elasticsearch中数据都存储在分片中,当执行搜索时每个分片独立搜索后,数据再经过整合返回.那么,如果要实现分页查询该怎么办呢? 更多内容参考Elasticsearch资料汇总 按照一般的查询 ...
- ElasticSearch—分页查询
ElasticSearch查询—分页查询详解 Elasticsearch中数据都存储在分片中,当执行搜索时每个分片独立搜索后,数据再经过整合返回.那么,如何实现分页查询呢? 按照一般的查询流程来说,如 ...
- elasticsearch 分页查询实现方案
1. from+size 实现分页 from表示从第几行开始,size表示查询多少条文档.from默认为0,size默认为10, 注意:size的大小不能超过index.max_result_wind ...
- ElasticSearch——分页查询
前言 ElasticSearch实现分页查询,有3种方式,他们在数据查询中各自占据着不同的优势,因此在搜索引擎的数据分页过程中,如何更好地利用各自的优势来进行数据查询是一个非常重要的过程. 传统分页( ...
- Elasticsearch分页查询
global index global CLIENT index = "guajibao-ipused-2019.10.13" CLIENT = Elasticsearch(hos ...
- Elasticsearch教程(九) elasticsearch 查询数据 | 分页查询
Elasticsearch 的查询很灵活,并且有Filter,有分组功能,还有ScriptFilter等等,所以很强大.下面上代码: 一个简单的查询,返回一个List<对象> .. ...
- elasticsearch查询之大数据集分页查询
一. 要解决的问题 search命中的记录特别多,使用from+size分页,直接触发了elasticsearch的max_result_window的最大值: { "error" ...
- Elasticsearch from/size-浅分页查询-深分页 scroll-深分页search_after深度查询区别使用及应用场景
Elasticsearch调研深度查询 1.from/size 浅分页查询 一般的分页需求我们可以使用from和size的方式实现,但是这种的分页方式在深分页的场景下应该是避免使用的.深分页的页次增加 ...
随机推荐
- image auto downloader
image auto downloader icons killer / js crawler http only + same-origin OK "use strict"; / ...
- JavaScript 如何使用 setTimeout 实现 setInterval
JavaScript 如何使用 setTimeout 实现 setInterval website multi content page setIntervalSimulator "use ...
- Axios all in one
Axios all in one https://github.com/axios/axios#example GET const axios = require('axios'); // Make ...
- Nestjs 验证对象数组
route @Patch(':id') patch(@Param('id') id: string, @Body() removeEssayDto: RemoveEssayDto) { return ...
- 疯狂的String
本文转载自疯狂的String 导语 在java中字符串是我们比较常用的一个类型,字符串是不可变的,类被声明为final , 存储字符的char[] value数据也被声明为final ,我们对Stri ...
- Github Packages和Github Actions实践之CI/CD
概述 Github在被微软收购后,不忘初心,且更大力度的造福开发者们,推出了免费私有仓库等大更新.近期又开放了packages和actions两个大招,经笔者试用后感觉这两个功能配合起来简直无敌. G ...
- Python和JavaScript在使用上有什么区别?
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://www.freecodecamp.org/news/python-vs-javas ...
- Excel_不打开文件进行跨工作簿查询
在使用Excel时,我们经常会遇到这种问题,我的数据源在表1里面,但是我要在表2里面做报表,用lookup和offset等公式都需要打开表1操作,否则就会报错.那么有没有办法在不打开表1的情况下在表2 ...
- Linux速通08 网络原理及基础设置、软件包管理
使用 ifconfig命令来维护网络 # ifconfig 命令:显示所有正在启动的网卡的详细信息或设定系统中网卡的 IP地址 # 应用 ifconfig命令设定网卡的 IP地址: * 例:修改 et ...
- 无限可能 | Flutter 2 重点更新一览
我们非常高兴在本周发布了 Flutter 2.自 Flutter 1.0 发布至今已有两年多的时间,在如此短暂的时间内,我们解决了 24,541 个 issue,合并了来自 765 个贡献者的 17, ...