【Elasticsearch教程21】分页查询以及Array数组排序 nested排序 详细案例

一、分页查询

1. 基本概念

默认情况下,ES搜索结果hits里有10条结果,我们可以使用fromsize这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_afterscroll来实现。
  • search afterscroll查询,我会在后面的博客里详细介绍。
分页方式优点缺点适用场景
from+size灵活,跳转页号
实现简单
有深分页问题数据量较小
只需浅分页
scroll解决了深度分页问题非实时数据,只是某刻快照数据
需要维护一个scroll_id
无法跳页号
海量数据导出
查询海量数据不在乎实时性
search_after性能最好,解决了深度分页问题
能够反映数据的实时变更
实现复杂,需要有一个全局唯一的字段
每一次查询都需要上次查询的结果
无法跳页号
海量数据的滚动分页

二. 排序条件

我们可以添加1个或多个排序字段 。排序的值可设descasc这2种。

1. 多字段排序

GET pigg_test_page/_search
{
  "from": 0,
  "size": 100,
  "sort": [
    {
      "name.keyword": "desc", 
      "id" : "asc"
    }
  ]
}

2. 在数组上排序

ES支持在数组上排序,可以选择minmaxsumavgmedian(中位数,仅在数值字段上)这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,其中examsnested类型

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": "语文"}
          }
        }
      }
    }
  ]
}
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为啥总是用户昵称已存在

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值