草庐IT

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

国服亚瑟 2024-04-28 原文

Elasticsearch 分页查询 排序 from size sort

一、分页查询

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": "语文"}
          }
        }
      }
    }
  ]
}

有关【Elasticsearch教程21】分页查询以及Array数组排序 nested排序 详细案例的更多相关文章

  1. ruby - 在 Ruby 中实现 `call_user_func_array` - 2

    我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)

  2. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  3. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  4. Ruby Koans about_array_assignment - 非平行与平行分配歧视 - 2

    通过ruby​​koans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John

  5. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  6. ruby-on-rails - Prawn PDF : I need to generate nested tables - 2

    我需要一个表,其中行实际上是2行表,一个嵌套表是..我怎样才能在Prawn中做到这一点?也许我需要延期..但哪一个? 最佳答案 现在支持子表:Prawn::Document.generate("subtable.pdf")do|pdf|subtable=pdf.make_table([["sub"],["table"]])pdf.table([[subtable,"original"]])end 关于ruby-on-rails-PrawnPDF:Ineedtogeneratenested

  7. arrays - 这是 Ruby 中 Array.fill 方法的错误吗? - 2

    这个问题在这里已经有了答案:Arraysmisbehaving(1个回答)关闭6年前。是否应该这样,即我误解了,还是错误?a=Array.new(3,Array.new(3))a[1].fill('g')=>[["g","g","g"],["g","g","g"],["g","g","g"]]它不应该导致:=>[[nil,nil,nil],["g","g","g"],[nil,nil,nil]]

  8. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  9. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  10. 在VMware16虚拟机安装Ubuntu详细教程 - 2

    在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主

随机推荐