Elasticsearch 分页查询 排序 from size sort
一、分页查询
1. 基本概念
默认情况下,ES搜索结果hits里有10条结果,我们可以使用from
和size
这2个参数实现分页查询。
from
默认是从0开始,指跳过多少条size
指最多返回多少条from=10, size=10
则允许返回第11~20条数据
GET pigg_test_page/_search
{
"from": 10,
"size": 10,
"sort": [
{
"id": {
"order": "asc"
}
}
]
}
2. 避免深分页
我们应该避免使用from
+size
来搜索太深的数据,ES有一个配置index.max_result_window
默认值是10000,当from
+size
> 10000时,ES返回会报错。
举例说明:某个index有3个分片,查询from = 10000,size=10
时,每个分片都会查询前10010条数据,然后3个分片的总共30030条数据合并起来再排序,取得真正的第10001~10010这10条数据。所以这样是非常低效率的。
- 如果我们是一个查询页面,一般没有必要让页号可以设置很大,一般页号设置最大100就满足业务上使用了,这样可以使用
from
+size
来分页。 - 如果我们是一个需要遍历整张表的逻辑,每次读取1000条并处理,这个可以使用search_after或scroll来实现。
search after
和scroll
查询,我会在后面的博客里详细介绍。
分页方式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
from+size | 灵活,跳转页号 实现简单 |
有深分页问题 | 数据量较小 只需浅分页 |
scroll | 解决了深度分页问题 | 非实时数据,只是某刻快照数据 需要维护一个scroll_id 无法跳页号 |
海量数据导出 查询海量数据不在乎实时性 |
search_after | 性能最好,解决了深度分页问题 能够反映数据的实时变更 |
实现复杂,需要有一个全局唯一的字段 每一次查询都需要上次查询的结果 无法跳页号 |
海量数据的滚动分页 |
二. 排序条件
我们可以添加1个或多个排序字段 。排序的值可设desc
和asc
这2种。
1. 多字段排序
GET pigg_test_page/_search
{
"from": 0,
"size": 100,
"sort": [
{
"name.keyword": "desc",
"id" : "asc"
}
]
}
2. 在数组上排序
ES支持在数组上排序,可以选择min
、max
、sum
、avg
和median
(中位数,仅在数值字段上)这5个比较选项。
PUT pigg_test_page/_doc/1
{
"id": 1,
"name": "name1",
"score": [98, 70, 10]
}
PUT pigg_test_page/_doc/2
{
"id": 2,
"name": "name2",
"score": [60, 50, 100]
}
按照成绩总分
进行由高到低排序
GET pigg_test_page/_search
{
"from": 0,
"size": 100,
"sort": [
{
"score": {
"order": "desc",
"mode": "sum"
}
}
]
}
3. 在nested嵌套字段上排序
创建一个index,其中exams
是nested
类型
PUT pigg_test_page/_mapping
{
"properties":{
"exams":{
"type":"nested",
"properties":{
"course":{
"type":"keyword"
},
"score":{
"type":"long"
}
}
},
"name":{
"type":"keyword"
}
}
}
插入2个学生的成绩
PUT pigg_test_page/_doc/1
{
"name": "name1",
"exams": [
{
"course": "语文",
"score": 98
},
{
"course": "数学",
"score": 100
}
]
}
PUT pigg_test_page/_doc/2
{
"name": "name2",
"exams": [
{
"course": "语文",
"score": 88
},
{
"course": "数学",
"score": 76
}
]
}
要按照语文成绩
由高到低排序:
GET pigg_test_page/_search
{
"sort": [
{
"exams.score": {
"order": "desc",
"nested": {
"path": "exams",
"filter": {
"term": {
"exams.course": "语文"}
}
}
}
}
]
}
4. 在Missing字段上排序
有些文档缺少指定的排序字段,可配置missing
为_first
或_last
这些文档在前还是在后。
接着上一个案例,插入一个缺少成绩的文档:
PUT pigg_test_page/_doc/3
{
"name": "name3"
}
指定缺少exams字段的文档显示在前
GET pigg_test_page/_search
{
"sort": [
{
"exams.score": {
"order": "desc",
"missing": "_first",
"nested": {
"path": "exams",
"filter": {
"term": {
"exams.course": "语文"}
}
}
}
}
]
}