【Elasticsearch】检索排序 & 分页_es 搜索引擎 查询结果排序
《Elasticsearch 检索》系列,共包含以下文章:
- 精准匹配检索(Exact Match)
- 全文检索 & 组合检索
- 检索高亮
- 检索排序 & 分页
- 深度分页及其替代方案
- 自定义评分检索
- 检索模板(Search Template)
😊 如果您觉得这篇文章有用 ✔️ 的话,请给博主一个一键三连 🚀🚀🚀 吧 (点赞 🧡、关注 💛、收藏 💚)!!!您的支持 💖💖💖 将激励 🔥 博主输出更多优质内容!!!
检索排序 & 分页
- 1.测试数据准备
- 2.排序功能
-
- 2.1 简单字段排序
- 2.2 多字段排序
- 2.3 日期排序
- 3.分页功能
-
- 3.1 基础分页
- 3.2 深度分页(不推荐大数据量使用)
- 3.3 使用 search_after 进行高效分页
- 4.综合示例:高亮+排序+分页
- 5.实践建议
1.测试数据准备
首先,我们创建一个名为 blog_posts
的索引,并插入一些测试数据:
PUT /blog_posts{ \"mappings\": { \"properties\": { \"title\": { \"type\": \"text\" }, \"content\": { \"type\": \"text\" }, \"author\": { \"type\": \"keyword\" }, \"views\": { \"type\": \"integer\" }, \"publish_date\": { \"type\": \"date\" }, \"tags\": { \"type\": \"keyword\" } } }}
POST /blog_posts/_bulk{\"index\":{}}{\"title\":\"Elasticsearch Basics\",\"content\":\"Learn the basics of Elasticsearch and how to perform simple queries.\",\"author\":\"John Doe\",\"views\":1500,\"publish_date\":\"2023-01-15\",\"tags\":[\"search\",\"database\"]}{\"index\":{}}{\"title\":\"Advanced Search Techniques\",\"content\":\"Explore advanced search techniques in Elasticsearch including aggregations and filters.\",\"author\":\"Jane Smith\",\"views\":3200,\"publish_date\":\"2023-02-20\",\"tags\":[\"search\",\"advanced\"]}{\"index\":{}}{\"title\":\"Data Analytics with ELK\",\"content\":\"How to use the ELK stack for data analytics and visualization.\",\"author\":\"John Doe\",\"views\":2800,\"publish_date\":\"2023-03-10\",\"tags\":[\"analytics\",\"elk\"]}{\"index\":{}}{\"title\":\"Elasticsearch Performance Tuning\",\"content\":\"Tips and tricks for optimizing Elasticsearch performance in production environments.\",\"author\":\"Mike Johnson\",\"views\":4200,\"publish_date\":\"2023-04-05\",\"tags\":[\"performance\",\"optimization\"]}{\"index\":{}}{\"title\":\"Kibana Dashboard Guide\",\"content\":\"Creating effective dashboards in Kibana for monitoring and analysis.\",\"author\":\"Jane Smith\",\"views\":1900,\"publish_date\":\"2023-05-12\",\"tags\":[\"kibana\",\"visualization\"]}
2.排序功能
能排序的字段都具备正排索引,单 text
类型字段是不可以排序的。如果要使 text
字段支持排序、聚合,则需要开启 fielddata
。
sort
是和 query
平级的,并不会被 query
包含。
2.1 简单字段排序
GET /blog_posts/_search{ \"query\": { \"match_all\": {} }, \"sort\": [ { \"views\": { \"order\": \"desc\" } } ]}
2.2 多字段排序
GET /blog_posts/_search{ \"query\": { \"match_all\": {} }, \"sort\": [ { \"author\": { \"order\": \"asc\" } }, { \"views\": { \"order\": \"desc\" } } ]}
2.3 日期排序
GET /blog_posts/_search{ \"query\": { \"match_all\": {} }, \"sort\": [ { \"publish_date\": { \"order\": \"desc\" } } ]}
3.分页功能
Elasticsearch 支持对查询结果进行分页处理,允许用户逐步获取和浏览大量数据。
在编写查询语句时,可通过再请求体中添加 from
和 size
字段实现分页。from
表示结果集的起始位置,而 size
表示每页返回的文档数量。
如果将 from
设置为 11 11 11,size
设置为 5 5 5,则返回的是第 10 10 10 ~ 14 14 14 条数据(默认从第 0 0 0 条开始)。
3.1 基础分页
GET /blog_posts/_search{ \"query\": { \"match_all\": {} }, \"from\": 0, \"size\": 2, \"sort\": [ { \"publish_date\": { \"order\": \"desc\" } } ]}
3.2 深度分页(不推荐大数据量使用)
深度分页 指的是在 Elasticsearch 中查询结果集 非常靠后的页码(例如第 1000 1000 1000 页,每页 10 10 10 条数据,即 from=10000
)。它通常表现为使用 from + size
参数组合来获取远端的分页数据。
❌ 不推荐的详细原因可参考我的另一篇博客:《【Elasticsearch】深度分页及其替代方案》。
当然,我们这里测试的数据没有那么多。
GET /blog_posts/_search{ \"query\": { \"match_all\": {} }, \"from\": 3, \"size\": 2}
3.3 使用 search_after 进行高效分页
首先获取第一页:
GET /blog_posts/_search{ \"query\": { \"match_all\": {} }, \"size\": 2, \"sort\": [ { \"views\": { \"order\": \"desc\" } }, { \"_id\": { \"order\": \"asc\" } } ]}
然后使用最后一个结果的排序值获取下一页:
GET /blog_posts/_search{ \"query\": { \"match_all\": {} }, \"size\": 2, \"search_after\": [3200, \"上一页最后一个文档的ID\"], \"sort\": [ { \"views\": { \"order\": \"desc\" } }, { \"_id\": { \"order\": \"asc\" } } ]}
4.综合示例:高亮+排序+分页
GET /blog_posts/_search{ \"query\": { \"multi_match\": { \"query\": \"search\", \"fields\": [\"title\", \"content\"] } }, \"highlight\": { \"fields\": { \"title\": {}, \"content\": { \"fragment_size\": 100, \"number_of_fragments\": 2 } } }, \"sort\": [ { \"views\": { \"order\": \"desc\" } } ], \"from\": 0, \"size\": 3}
5.实践建议
- 对于大文本字段,限制
fragment_size
和number_of_fragments
以提高性能。 - 考虑使用
require_field_match: true
来只高亮查询中指定的字段。
- 对于文本字段排序,使用
.keyword
子字段或设置fielddata: true
。 - 避免对未索引或分析的字段进行排序。
- 对于分页场景,使用包含唯一值的排序条件(如
_id
)。
- 避免深度分页(超过 1000 1000 1000 条记录)),使用
search_after
代替。 - 对于无限滚动等场景,优先考虑
search_after
而不是from/size
。 - 考虑使用滚动 API(Scroll API)对于大数据量导出场景。