ES 简介

Elasticsearch 是一个基于 Lucene 实现的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful web 接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elasticsearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

ES 的特点:

分布式实时文件存储,可以将每一个字段都编入索引,使其可以被检索

可以作为一个大型分布式集群(数百台服务器)技术,处理PB级数据

Elasticsearch不是什么新技术,主要是将全文检索、数据分析以及分布式技术,合并在了一起,才形成了独一无二的ES。

下面介绍下Java中Elasticsearch 实现分页的 3 种方式,还有谁不会??

一、from + size 浅分页

"浅"分页可以理解为简单意义上的分页。

它的原理很简单,就是查询前20条数据,然后截断前10条,只返回10-20的数据。这样其实白白浪费了前10条的查询。

GET test_dev/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"age": 28
}
}
]
}
},
"size": 10,
"from": 20,
"sort": [
{
"timestamp": {
"order": "desc"
},
"_id": {
"order": "desc"
}
}
]
}

其中,from定义了目标数据的偏移值,size定义当前返回的数目。默认from为0,size为10,即所有的查询默认仅仅返回前10条数据。

在这里有必要了解一下from/size的原理:

因为es是基于分片的,假设有5个分片,from=100,size=10。则会根据排序规则从5个分片中各取回100条数据数据,然后汇总成500条数据后选择最后面的10条数据。

做过测试,越往后的分页,执行的效率越低。总体上会随着from的增加,消耗时间也会增加。而且数据量越大,就越明显!

二、scroll 深分页

from+size查询在10000-50000条数据(1000到5000页)以内的时候还是可以的,但是如果数据过多的话,就会出现深分页问题。

为了解决上面的问题,elasticsearch提出了一个scroll滚动的方式。

scroll 类似于sql中的cursor,使用scroll,每次只能获取一页的内容,然后会返回一个scroll_id。根据返回的这个scroll_id可以不断地获取下一页的内容,所以scroll并不适用于有跳页的情景。

GET test_dev/_search?scroll=5m
{
"query": {
"bool": {
"filter": [
{
"term": {
"age": 28
}
}
]
}
},
"size": 10,
"from": 0,
"sort": [
{
"timestamp": {
"order": "desc"
},
"_id": {
"order": "desc"
}
}
]
}
  • scroll=5m表示设置scroll_id保留5分钟可用。
  • 使用scroll必须要将from设置为0。
  • size决定后面每次调用_search搜索返回的数量

然后我们可以通过数据返回的_scroll_id读取下一页内容,每次请求将会读取下10条数据,直到数据读取完毕或者scroll_id保留时间截止:

GET _search/scroll
{
"scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAJZ9Fnk1d......",
"scroll": "5m"
}

注意:请求的接口不再使用索引名了,而是 _search/scroll,其中GET和POST方法都可以使用。

scroll删除

根据官方文档的说法,scroll的搜索上下文会在scroll的保留时间截止后自动清除,但是我们知道scroll是非常消耗资源的,所以一个建议就是当不需要了scroll数据的时候,尽可能快的把scroll_id显式删除掉。

清除指定的scroll_id

DELETE _search/scroll/DnF1ZXJ5VGhlbkZldGNo.....

清除所有的scroll:

DELETE _search/scroll/_all

三、search_after 深分页

scroll 的方式,官方的建议不用于实时的请求(一般用于数据导出),因为每一个 scroll_id 不仅会占用大量的资源,而且会生成历史快照,对于数据的变更不会反映到快照上。

search_after 分页的方式是根据上一页的最后一条数据来确定下一页的位置,同时在分页请求的过程中,如果有索引数据的增删改查,这些变更也会实时的反映到游标上。但是需要注意,因为每一页的数据依赖于上一页最后一条数据,所以无法跳页请求。

为了找到每一页最后一条数据,每个文档必须有一个全局唯一值,官方推荐使用 _uid 作为全局唯一值,其实使用业务层的 id 也可以。

GET test_dev/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"age": 28
}
}
]
}
},
"size": 20,
"from": 0,
"sort": [
{
"timestamp": {
"order": "desc"
},
"_id": {
"order": "desc"
}
}
]
}
  • 使用search_after必须要设置from=0
  • 这里我使用timestamp和_id作为唯一值排序。
  • 我们在返回的最后一条数据里拿到sort属性的值传入到search_after

使用sort返回的值搜索下一页:

GET test_dev/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"age": 28
}
}
]
}
},
"size": 10,
"from": 0,
"search_after": [
1541495312521,
"d0xH6GYBBtbwbQSP0j1A"
],
"sort": [
{
"timestamp": {
"order": "desc"
},
"_id": {
"order": "desc"
}
}
]
}

到此这篇关于Elasticsearch 实现分页的 3 种方式,还有谁不会??的文章就介绍到这了,更多相关Elasticsearch 实现分页内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

Java中Elasticsearch 实现分页方式(三种方式)的更多相关文章

  1. Java中 实现多线程成的三种方式(继承,实现,匿名内部类)

    ---------------------------------------------------------------------------------------------------- ...

  2. Java中从控制台输入的三种方式

    我们最熟悉的从控制台读取一个字符或者一个字符串都知道用Scanner,那么除了Scanner还有没有其他的呢,答案是有的,我们来看看. System.in.read() System.in.read( ...

  3. JAVA中使用LDAP登录的三种方式

    搜索中关于java 登录ldap,大部分会采用  cn=xxx,ou=xxx,dc=xxx的方式,此处的cn是用户的Display Name,而不是account,而且如果ou有多层,比如我们的OU就 ...

  4. Java中获取键盘输入值的三种方法

    Java中获取键盘输入值的三种方法     Java程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值 ...

  5. Java反射获取class对象的三种方式,反射创建对象的两种方式

    Java反射获取class对象的三种方式,反射创建对象的两种方式 1.获取Class对象 在 Java API 中,提供了获取 Class 类对象的三种方法: 第一种,使用 Class.forName ...

  6. 在Tomcat中部署web项目的三种方式

    搬瓦工搭建SS教程 SSR免费节点:http://www.xiaokeli.me 在这里介绍在Tomcat中部署web项目的三种方式: 1.部署解包的webapp目录 2.打包的war文件 3.Man ...

  7. Tomcat中部署web应用的三种方式

    Tomcat中部署web应用的三种方式(静态部署)       第一种,针对war或解压后的war,最为常用的是直接操作webapp目录,将完整的war包或者web应用直接放到webapp目录下.使用 ...

  8. spring中创建bean对象的三种方式以及作用范围

    时间:2020/02/02 一.在spring的xml配置文件中创建bean对象的三种方式: 1.使用默认构造函数创建.在spring的配置文件中使用bean标签,配以id和class属性之后,且没有 ...

  9. 【java多线程】多线程的创建三种方式--笔记

    申明:线程的概念以及进程的相关概念,可以参考网络上其他资料,这里只讨论多线程是怎么实现. 一.多线程的简单理解 明白什么是多线程,小生通俗一点的理解为:在一个程序里,我想同时让这个程序完成多个任务. ...

  10. java 中创建线程有哪几种方式?

    Java中创建线程主要有三种方式: 一.继承Thread类创建线程类 (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务.因此把run()方法称为执行 ...

随机推荐

  1. day49-JDBC和连接池05

    JDBC和连接池05 11.BasicDAO 先来分析一个问题 前面我们使用了Apache-DBUtils和Druid简化了JDBC开发,但仍存在以下不足: SQL语句是固定的,不能通过参数传入,通用 ...

  2. HTTPS涉及的加密算法讲解

    前言 从2015年左右开始,Google.Baidu.Facebook 等互联网巨头,不谋而合地开始大力推行 HTTPS, 国内外的大型互联网公司很多也都已经启用了全站 HTTPS 为鼓励全球网站的 ...

  3. java实现单链表的创建、增、删、改、查

    文章目录 单链表的创建.增.删.改.查 1.增加一个节点 2.删除一个节点 3.修改某一个节点 5.遍历单链表 单链表的创建.增.删.改.查 双向链表的增删改查:https://blog.csdn.n ...

  4. LeetCode------合并两个有序数组(4)【数组】

    来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/merge-sorted-array 1.题目 给你两个按 非递减顺序 排列的整数数组 nums ...

  5. 小米MIUI禁止系统更新

    删除downloaded_rom的文件夹,随便找一个文件(文件,不是文件夹),重名为downloaded_rom(是把一个文件重命名),这样系统后台偷偷下载时,就不知道该存放更新包的文件,就无法偷偷更 ...

  6. while循环条件不成立却无法跳出死循环的问题

    在进入循环的时候,实际上是将A从内存加载到寄存器里面运行的,在整个循环中,A这个变量都只是在读取寄存器里面的值. 而当进入中断的时候,中断里面会从内存加载A到寄存器,修改完之后又存到内存里,然后退出中 ...

  7. java代码整洁之道

    package Day01;import org.junit.Test;import java.text.NumberFormat;import java.util.Scanner;public cl ...

  8. Docker容器化技术

    1. 初始Docker 1.1 Docker概念 Docker概念:Docker是一个开源的应用容器引擎 诞生于2013年初,基于Go实现,dotCloud公司出品(后改名为Docker Inc) D ...

  9. freeswitch的mod_curl模块

    概述 有时候,我们需要在呼叫的过程中,或过程后调用web api接口. freeswitch的mod_curl模块可以很方便的实现web api的接口调用. mod_curl模块默认不安装,需要进入模 ...

  10. 微信DAT文件解密(dat转图像)

    微信电脑版现在已经是日常工作生活必不可少的工具,有时候删除了聊天记录或者被系统清理软件清理了,但还想查看曾经的微信聊天图片. 这个时候辛辛苦苦找到了文件,却发现无法查看,因为微信电脑版为了保护我们的隐 ...