当前位置: 首页 > news >正文

Elasticsearch 之分页查询

Elasticsearch 之分页查询

引言

在搜索引擎应用中,分页查询是一种常见需求。Elasticsearch 提供了多种分页方式以应对不同场景。本文将结合实际应用场景,介绍三种常用的分页查询方法

From + Size 分页查询

GET /content_item_profile/_search
{"from": 0,"size":20,"query": {"match": {"title": "字节跳动"}},"sort": [{"born_time": {"order": "desc"}}]
}
  • 上述 ES 查询语句共返回20条结果
  • From + Size 查询的优缺点
    • 优点: 支持随机翻页
    • 缺点
      • 受制于 max_result_window 设置,不能无限制翻页
      • 存在深度翻页问题,越往后翻页越慢
      • 不推荐使用 from + size 做深度分页查询的核心原因
        • 搜索请求通常跨越多个分片,每个分片必须将其请求的命中内容以及任何先前页面的命中内容加载到内存中
        • CPU: 每个分片和协调节点都需要进行大规模排序,CPU压力巨大
        • 内存:协调节点需要创建一个容量为 from + size的优先级队列来存储和排序所有分片的结果,大量消耗堆内存
        • 带宽:分片和协调节点之间需要传输大量数据,占用网络带宽
        • 响应时间:整个过程非常缓慢,延迟可能从毫秒级变为秒级甚至分钟级
  • From + Size 分页查询适用场景
    • 小型数据集
    • 搜索引擎随机跳转分页的业务场景

search_after 查询

search_after 避免使用昂贵的 from,它使用上一页最后一个结果的排序值作为起点来获取下一页。查询时需要指定上一页最后一个文档的排序值。ES 创建一个时间点 Point In Time(PIT)保障搜索过程中保留特定事件点的索引状态。search_after 分页查询可以简单概括为如下几个步骤

  • 步骤 1:创建 PIT 视图
POST /job_item_profile_prod20240112181802/_pit?keep_alive=1m

返回结果:

{"id" : "64O1AwMjam9iX2l0ZW1fcHJvZmlsZV9wcm9kMjAyNDAxMTIxODE4MDIWMHpKY3VEanJTYnU4dXBpTGhLZjd2ZwAWTDhJS1lfME1SRUdfNldWMUIwZlNFQQAAAAAAFd1wmxZEMFZYb1RudlJIaS1seW9PWTdyZktnACNqb2JfaXRlbV9wcm9maWxlX3Byb2QyMDI0MDExMjE4MTgwMhYwekpjdURqclNidTh1cGlMaEtmN3ZnARZuSHhjd1hQRlRlV1ZPVzFlVDZmSXJBAAAAAAAXrPHvFlFpelRRcEJsUXlXZXg4VTVEZGJ6VFEAI2pvYl9pdGVtX3Byb2ZpbGVfcHJvZDIwMjQwMTEyMTgxODAyFjB6SmN1RGpyU2J1OHVwaUxoS2Y3dmcCFm02TVZRNGl4U2NxY0hpeTlQaFF3NHcAAAAAABbwjhcWUllXVWJWLXNUMDIxZnJCbGJhb3dqdwABFjB6SmN1RGpyU2J1OHVwaUxoS2Y3dmcAAA=="
}

获取数据量

POST /job_item_profile_prod20240112181802/_count

返回结果:

{"count" : 337562,"_shards" : {"total" : 3,"successful" : 3,"skipped" : 0,"failed" : 0}
}

keep_alive=1m,代表视图保留时间是1分钟,超过1分钟执行会报错如下

{"error" : {"root_cause" : [{"type" : "search_context_missing_exception","reason" : "No search context found for id [384877637]"}]},"status" : 404
  • 步骤 2:创建基础查询语句,这里要设置翻页的条件
GET /_search
{"size":10,"query": {"match" : {"job_name" : "java"}},"pit": {"id":  "64O1AwMjam9iX2l0ZW1fcHJvZmlsZV9wcm9kMjAyNDAxMTIxODE4MDIWMHpKY3VEanJTYnU4dXBpTGhLZjd2ZwAWbTZNVlE0aXhTY3FjSGl5OVBoUXc0dwAAAAAAFvDERRZSWVdVYlYtc1QwMjFmckJsYmFvd2p3ACNqb2JfaXRlbV9wcm9maWxlX3Byb2QyMDI0MDExMjE4MTgwMhYwekpjdURqclNidTh1cGlMaEtmN3ZnARZMOElLWV8wTVJFR182V1YxQjBmU0VBAAAAAAAV3Z7zFkQwVlhvVG52UkhpLWx5b09ZN3JmS2cAI2pvYl9pdGVtX3Byb2ZpbGVfcHJvZDIwMjQwMTEyMTgxODAyFjB6SmN1RGpyU2J1OHVwaUxoS2Y3dmcCFm02TVZRNGl4U2NxY0hpeTlQaFF3NHcAAAAAABbwxEYWUllXVWJWLXNUMDIxZnJCbGJhb3dqdwABFjB6SmN1RGpyU2J1OHVwaUxoS2Y3dmcAAA==", "keep_alive": "1m"},"sort": [ {"edu_level": "asc"}]
}

PIT 和索引不能同时使用,设置了PIT,检索时候就不需要再指定索引,两者一起使用会报下面的错误

{"error" : {"root_cause" : [{"type" : "action_request_validation_exception","reason" : "Validation Failed: 1: [indices] cannot be used with point in time. Do not specify any index with point in time.;"}],"type" : "action_request_validation_exception","reason" : "Validation Failed: 1: [indices] cannot be used with point in time. Do not specify any index with point in time.;"},"status" : 400
}

在每个返回文档的最后,sort 会有两个结果值,如下所示:

{"pit_id" : "64O1AwMjam9iX2l0ZW1fcHJvZmlsZV9wcm9kMjAyNDAxMTIxODE4MDIWMHpKY3VEanJTYnU4dXBpTGhLZjd2ZwAWTDhJS1lfME1SRUdfNldWMUIwZlNFQQAAAAAAFd20khZEMFZYb1RudlJIaS1seW9PWTdyZktnACNqb2JfaXRlbV9wcm9maWxlX3Byb2QyMDI0MDExMjE4MTgwMhYwekpjdURqclNidTh1cGlMaEtmN3ZnARZuSHhjd1hQRlRlV1ZPVzFlVDZmSXJBAAAAAAAXrUI0FlFpelRRcEJsUXlXZXg4VTVEZGJ6VFEAI2pvYl9pdGVtX3Byb2ZpbGVfcHJvZDIwMjQwMTEyMTgxODAyFjB6SmN1RGpyU2J1OHVwaUxoS2Y3dmcCFm02TVZRNGl4U2NxY0hpeTlQaFF3NHcAAAAAABbw3WUWUllXVWJWLXNUMDIxZnJCbGJhb3dqdwABFjB6SmN1RGpyU2J1OHVwaUxoS2Y3dmcAAA==","took" : 15,"timed_out" : false,"_shards" : {"total" : 3,"successful" : 3,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 10000,"relation" : "gte"},"max_score" : null,"hits" : [{"_index" : "job_item_profile_prod20240112181802","_type" : "_doc","_id" : "658a3a55aec19df69534f217","_score" : null,"_source" : {"id" : 30100000262389,...},"sort" : [0,94]},...
  • 返回的 sort数组 [0, 94]分别代表
    • 0: 这是当前文档 _source.edu_level字段的排序值。从 _source里可以看到 “edu_level”: 0,所以这里就是 0
    • 94: 这是当前文档 _id字段 (658a3a55aec19df69534f217) 的内部排序表示。Elasticsearch 不会直接返回字符串形式的 _id用于 search_after,而是会将其转换成一个更高效的、可用于比较的数字或哈希值。94就是这个内部值
      • Note: Elasticsearch 有一个内置的保障机制:为了确保排序结果的唯一性和分页的准确性,如果提供的排序条件不足以唯一确定所有文档的顺序,它会自动添加一个隐式的、基于文档 _id的排序条件作为最终决胜局(Tiebreaker)

步骤3:实现后续翻页

GET /_search
{"size": 10,"query": {"match": {"job_name": "java"}},"pit": {"id": "64O1AwMjam9iX2l0ZW1fcHJvZmlsZV9wcm9kMjAyNDAxMTIxODE4MDIWMHpKY3VEanJTYnU4dXBpTGhLZjd2ZwAWTDhJS1lfME1SRUdfNldWMUIwZlNFQQAAAAAAFd20khZEMFZYb1RudlJIaS1seW9PWTdyZktnACNqb2JfaXRlbV9wcm9maWxlX3Byb2QyMDI0MDExMjE4MTgwMhYwekpjdURqclNidTh1cGlMaEtmN3ZnARZuSHhjd1hQRlRlV1ZPVzFlVDZmSXJBAAAAAAAXrUI0FlFpelRRcEJsUXlXZXg4VTVEZGJ6VFEAI2pvYl9pdGVtX3Byb2ZpbGVfcHJvZDIwMjQwMTEyMTgxODAyFjB6SmN1RGpyU2J1OHVwaUxoS2Y3dmcCFm02TVZRNGl4U2NxY0hpeTlQaFF3NHcAAAAAABbw3WUWUllXVWJWLXNUMDIxZnJCbGJhb3dqdwABFjB6SmN1RGpyU2J1OHVwaUxoS2Y3dmcAAA==","keep_alive": "1m"},"sort": [{"edu_level": "asc"}],"search_after": [0, 94] 
}

后续翻页都可以借助 search_after 指定前一页的最后一个文档的 sort 字段值

  • search_after 查询的优缺点
    • 优点:不严格受制于 max_result_window,可以无限制往后翻页
    • 缺点:只支持向后翻页,不支持随机翻页
  • search_after 分页查询适用场景
    • 适合手机端搜索,下拉刷新式的翻页

Scroll 遍历查询

scroll 支持全量遍历,详细操作可以参阅 Elasticsearch scroll 之滚动查询~

  • Scroll 查询的优缺点
    • 优点:支持全量遍历
    • 缺点
      • 单次遍历的 size 值也不能超过 max_result_window 大小
      • 保留上下文需要足够的堆内存空间
      • 响应时间非实时
    • Note: Scroll 为旧版全量遍历方式。ES 官方推荐的现代方式是 search_after + PIT 的方式来进行全量遍历

参考文献

[1] Elasticsearch最佳生产实践,推荐收藏!
https://zhuanlan.zhihu.com/p/1904124363642479029
[2] ElasticSearch三种分页方式以及各优缺点.
https://blog.csdn.net/gongzi_9/article/details/124681107
[3] Elasticsearch scroll 之滚动查询.
https://blog.csdn.net/m0_38031488/article/details/144211722?spm=1001.2014.3001.5501

http://www.dtcms.com/a/449370.html

相关文章:

  • apache hop 不能处理clickhouse 数组格式怎么办?
  • 网站建设 网站设计php语言网站开发公司北京
  • 代码审计
  • 制作网站需要钱吗天津网址
  • cursor使用之没有正常的编辑器中的运行箭头
  • 建设网站优化创意网站建设价格多少
  • soular入门到实战(3) - 如何实现TikLab工具链统一登录认证
  • Python图形界面——海龟绘图
  • 《强化学习数学原理》学习笔记9——值迭代算法
  • 网站建设 统一标准体系什么是网络销售
  • 网站开发语言有哪几种临沂专业网站制作
  • 花店网站建设方案网站木马文件删除
  • Bash 的基本语法总结
  • 网站怎么进行优化网站开发 英文文章
  • 自动驾驶决策规划算法(开幕式)
  • 从零起步学习Redis || 第八章:过期删除策略与内存淘汰策略详解及实战使用(LRU和LFU算法详解)
  • 自动驾驶中的传感器技术65——Navigation(2)
  • 知识体系_scala_利用scala和spark构建数据应用
  • 备案后网站打不开沈阳营销网站建设
  • AI编辑器(FIM补全,AI扩写)简介
  • 优设网设计师导航最新seo快排技术qq
  • 【C++】哈希和哈希封装unordered_map、unordered_set
  • VS Code安装即环境配置
  • 从 LiveData 到 Flow:状态、事件、背压与回调全面实战
  • 数据库与缓存数据一致性的全部方案
  • 算命公司网站建设制作开发方案网站商城怎么做app
  • 遗传算法解决TSP问题
  • MVC的含义
  • DBSCAN 密度聚类算法
  • 【极客日常】用Eino+Ollama低成本研发LLM的Agent