Elasticsearch使用Easy-Es + RestHighLevelClient实现深度分页跳页
注意!!!博主只在测试环境试了一下,没有发到生产环境跑。因为代码还没写完客户说不用弄了( •̩̩̩̩_•̩̩̩̩ ) 也好,少个功能少点BUG
使用from + size的时候发现存在max_result_window=10000的限制,于是研究使用别的方法,最终想出个歪招来实现深度分页跳页。
1、三种分页方式比较



2、实现过程
- BaseEsMapper构建查询条件
- RestHighLevelClient实现scroll大分页滚动查询
- 判断是否跨页,如果跨页滚动拿到两页数据
- 根据前端分页参数进行数据截取返回
3、实现代码
引入依赖
<dependency><groupId>org.dromara.easy-es</groupId><artifactId>easy-es-boot-starter</artifactId><version>2.0.0</version>
</dependency>
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-client</artifactId><version>7.6.2</version>
</dependency>
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.6.2</version>
</dependency>
SearchResult
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;@Data
public class SearchResult<T> implements Serializable {private int total;private List<DocBaseEntity<T>> source = new ArrayList<>();private JSONObject aggregations;private String scrollId;public void addData(DocBaseEntity<T> obj){source.add(obj);}public List<T> getDatas(){return source.stream().map(DocBaseEntity::getDatas).collect(Collectors.toList());}public void addDatas(List<DocBaseEntity<T>> objs){source.addAll(objs);}public void setTotal(Object total){this.total = Integer.parseInt(String.valueOf(total));}public JSONObject toJSONObject(){return JSONUtil.parseObj(this,true);}
}
DocBaseEntity
import cn.hutool.json.JSONObject;
import lombok.Data;
import org.elasticsearch.search.SearchHit;
import java.io.Serializable;@Data
public class DocBaseEntity<T> implements Serializable {private String _index;private String _type;private String _id;private T datas;public DocBaseEntity(SearchHit data) {this._index = data.getIndex();this._type = data.getType();this._id = data.getId();}public DocBaseEntity(JSONObject jsonHits){this._index = jsonHits.getStr("_index");this._type = jsonHits.getStr("_type");this._id = jsonHits.getStr("_id");}public T getDatas(){return datas;}}
RestClientConfig
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RestClientConfig {@Value("${elasticsearch.clientIps}")private String clientIps;@Value("${elasticsearch.httpPort}")private int httpPort;@Value("${elasticsearch.username}")private String username;@Value("${elasticsearch.password}")private String password;private HttpHost[] getHttpHosts(String clientIps, int esHttpPort) {String[] clientIpList = clientIps.split(",");HttpHost[] httpHosts = new HttpHost[clientIpList.length];for (int i = 0; i < clientIpList.length; i++) {httpHosts[i] = new HttpHost(clientIpList[i], esHttpPort, "http");}return httpHosts;}/*** 创建带HTTP Basic Auth认证rest客户端*/@Beanpublic RestHighLevelClient restHighLevelClient() {CredentialsProvider credentialsProvider = new BasicCredentialsProvider();credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));return new RestHighLevelClient(RestClient.builder(getHttpHosts(clientIps, httpPort)).setHttpClientConfigCallback((HttpAsyncClientBuilder httpAsyncClientBuilder) -> httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider)));}
}
滚动查询方法
@Autowired
private RestHighLevelClient restHighLevelClient;/*** 滚动查询* @param indexName* @param pageNo* @param pageSize* @param scrollId* @param resultObj* @param wrapper* @param <T>* @return* @throws IOException*/
public <T> SearchResult<T> scrollSearchElasticSearchDatas(String indexName,int pageNo,int pageSize,String scrollId,Class<T> resultObj,LambdaEsQueryWrapper<ES实体类Bean> wrapper) throws IOException {SearchSourceBuilder searchSourceBuilder = rdsBookCommonDetailEsMapper.getSearchSourceBuilder(wrapper);searchSourceBuilder.size(pageSize);SearchRequest searchRequest = new SearchRequest(indexName);searchRequest.source(searchSourceBuilder);//设定scroll失效时长Scroll scroll = new Scroll(TimeValue.timeValueMinutes(3));searchRequest.scroll(scroll);SearchResponse searchResponse = null;if(StrUtil.isEmpty(scrollId)){searchResponse = executSearch(searchRequest);String tempscrollId = searchResponse.getScrollId();SearchScrollRequest searchScrollRequest = new SearchScrollRequest(tempscrollId);searchScrollRequest.scroll(scroll);for (int i = 0; i < (pageNo -1); i++) {searchResponse = scrollSearch(searchScrollRequest);}scrollId = tempscrollId;}else {SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);searchResponse = scrollSearch(searchScrollRequest);}//构建结果SearchResult<T> result = createSearchResult(searchResponse,resultObj);result.setScrollId(scrollId);return result;
}/*** 执行查询*/
private SearchResponse executSearch(SearchRequest searchRequest) {SearchResponse searchResponse = null;try{searchResponse = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);}catch(Exception e){//异常处理}return searchResponse;
}/*** 滚动查询执行* @param searchScrollRequest* @return*/
private SearchResponse scrollSearch(SearchScrollRequest searchScrollRequest){SearchResponse searchResponse = null;try{searchResponse = restHighLevelClient.scroll(searchScrollRequest,RequestOptions.DEFAULT);}catch(Exception e){//异常处理}return searchResponse;
}/*** 构建目标结果* @param response 返回参数* @param resultObj 类对象* @param <T>* @return*/
private <T> SearchResult<T> createSearchResult(SearchResponse response,Class<T> resultObj){SearchResult<T> resultMap = new SearchResult<>();SearchHit[] datas = response.getHits().getHits();for(SearchHit data:datas){DocBaseEntity<T> temp = new DocBaseEntity<>(data);temp.setDatas(JSONUtil.toBean(JSONUtil.parseObj(data.getSourceAsMap()),resultObj));resultMap.addData(temp);}resultMap.setTotal(response.getHits().getTotalHits().value);return resultMap;
}/*** 关闭scroll* @param scrollId* @throws IOException*/
private void clearScrollSession(String scrollId) throws IOException {if (scrollId != null) {ClearScrollRequest clearScrollRequest = new ClearScrollRequest();clearScrollRequest.addScrollId(scrollId);ClearScrollResponse clearScrollResponse = restHighLevelClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);clearScrollResponse.isSucceeded();}
}
使用
LambdaEsQueryWrapper<ES实体类Bean> wrapper = new LambdaEsQueryWrapper<>();
wrapper.eqxxx
...构建各种查询条件
// 游标id
String scrollId = "";
// 第一次查询
SearchResult<ES实体类Bean> firstSearchResult = null;
// 第二次查询
SearchResult<ES实体类Bean> secondSearchResult = null;
// 每次滚动查询5000条数据,根据前端传的分页参数决定要滚动到哪一页
int maxPage = ((searchCommonDetaiVo.getCurrentPage() * searchCommonDetaiVo.getPageSize()) / 5000) + 1;
try {firstSearchResult = scrollSearchElasticSearchDatas("IndexName", maxPage, 5000, scrollId, ES实体类Bean.class, wrapper);scrollId = firstSearchResult.getScrollId();
} catch (IOException e) {e.printStackTrace();
}
// 判断是否跨页
if (searchCommonDetaiVo.getPageSize() > (searchCommonDetaiVo.getCurrentPage() * searchCommonDetaiVo.getPageSize()) % 5000) {try {secondSearchResult = scrollSearchElasticSearchDatas("IndexName", maxPage-1, 5000, scrollId, ES实体类Bean.class, wrapper);} catch (IOException e) {e.printStackTrace();}
}
// TODO 根据前端分页参数截取数据返回
try {clearScrollSession(scrollId);
} catch (IOException e) {log.info("游标清理失败");e.printStackTrace();
}
相关文章:
Elasticsearch使用Easy-Es + RestHighLevelClient实现深度分页跳页
注意!!!博主只在测试环境试了一下,没有发到生产环境跑。因为代码还没写完客户说不用弄了( •̩̩̩̩_•̩̩̩̩ ) 也好,少个功能少点BUG 使用from size的时候发现存在max_result_window10000的限制&…...
基于ASRPRO的语音应答
做这个的起因是为了送女朋友,而且这东西本身很简单,所以在闲暇之余尝试了一下。 这个工程很简单,只通过对ASRPRO进行编程即可。 先看效果。(没有展示所有效果,后续会列出来所有对话触发) 语音助手示例1 语音助手示例2 代码部分使用天文Block编辑,找了一圈好像只…...
3D看车汽车案例,车模一键换皮肤,开关车门,轴距,电池功能
3D 汽车案例 网址: http://car.douchuanwei.com/...
数据结构-4.栈与队列
本篇博客给大家带来的是栈和队列的知识点, 其中包括两道面试OJ题 用队列实现栈 和 用栈实现队列. 文章专栏: Java-数据结构 若有问题 评论区见 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条, 如果分享不成功, 那我就会回你一下,那样你就分享成功啦. 你们的…...
芝士AI写作有什么特色? 大模型支撑,智能改写续写,让写作更轻松
又到了一年的毕业季,大学四年眨眼间匆匆就过去了,毕业,求职,考研,工作,升学,但是在这之前,我们必须要完成论文的写作,这也是每一位大学生都必须要面对~ 芝士AI官网&…...
【计网】从零开始学习http协议 --- http的请求与应答
如果你不能飞,那就跑; 如果跑不动,那就走; 实在走不了,那就爬。 无论做什么,你都要勇往直前。 --- 马丁路德金 --- 从零开始学习http协议 1 什么是http协议2 认识URL3 http的请求和应答3.1 服务端设计…...
记录linux环境下搭建本地MQTT服务器实现mqtt的ssl加密通讯
1、ubuntu安装mosquitto sudo apt-get update//安装服务端 sudo apt-get install mosquitto//安装客户端 sudo apt-get install mosquitto-clients 2、安装openssl 3、mqtts/tls加密传输 mosquitto原生支持了TLS加密,TLS(传输层安全)是SSL&…...
基于python+django+vue的电影数据分析及可视化系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏:Java精选实战项目…...
HJ50-四则运算:栈的运用、中缀表达式转后缀表达式并计算结果
文章目录 题目一、分析1.1表达式预处理1.2中缀表达式转后缀1.3 后缀表达式计算结果 二、答案 题目 一、分析 通过利用栈将中缀表达式转换为后缀表达式,在根据后缀表达式计算运算结果。由于包含负数操作数的情况,并且操作数位数不固定为1,因此…...
C++编程:实现简单的高精度时间日志记录小程序
0. 概述 为了检查是否存在系统时间跳变,本文使用C实现了一个简单的高精度时间日志记录小程序。该程序能够每隔指定时间(默认40毫秒)记录一次系统时间到文件中,并具备以下功能: 自定义时间间隔和文件名:通…...
QQ机器人搭建
使用QQ官方机器人Python SDK和三方框架搭建QQ群聊机器人 文章目录 使用QQ官方机器人Python SDK和三方框架搭建QQ群聊机器人前言编写机器人代码机器人监听群聊进行文字回复机器人监听群聊进行图片回复机器人监听群聊进行文件发送机器人监听群聊进行视频发送机器人监听群聊进行语…...
flink设置保存点和恢复保存点
增加了hdfs package com.qyt;import org.apache.flink.api.java.functions.KeySelector; import org.apache.flink.api.java.tuple.Tuple2;import org.apache.flink.runtime.state.storage.FileSystemCheckpointStorage;import org.apache.flink.streaming.api.datastream.Dat…...
使用python获取百度一下,热搜TOP数据详情
一、查找对应链接 # 警告:以下代码仅供学习和交流使用,严禁用于任何违法活动。 # 本代码旨在帮助理解和学习编程概念,不得用于侵犯他人权益或违反法律法规的行为。 1、打开百度页面 百度一下,你就知道 2、点击F12 或 右键鼠标…...
Go conc库学习与使用
文章目录 主要功能和特点conc 的安装典型使用场景示例代码并行执行多个 Goroutines错误处理限制并发 Goroutines 数量使用 context.Context 进行任务控制 常见问题1. **任务中发生 panic**原因:解决方法: 2. **conc.Group 重复调用 Wait()**原因…...
大模型prompt先关
对于未出现的任务,prompt编写技巧: 1、假设你是资深的摘要生成专家,根据提供的内容,总结对应的摘要信息。请生成一个指令,指令中带有一个使用例子。直接提供给大型模型以执行此任务。 2、基于大模型提供的内容再进行二…...
尚品汇-自动化部署-Jenkins的安装与环境配置(五十六)
目录: 自动化持续集成 (1)环境准备 (2)初始化 Jenkins 插件和管理员用户 (3)工作流程 (4)配置 Jenkins 构建工具 自动化持续集成 互联网软件的开发和发布…...
【尚跑】2024铜川红色照金半程马拉松赛,大爬坡152安全完赛
1、赛事背景 2024年9月22日8点,2024铜川红色照金半程马拉松赛于照金1933广场鸣枪起跑! 起跑仪式上,6000位选手们合唱《歌唱祖国》,熟悉的旋律响彻陕甘边革命根据地照金纪念馆前,激昂的歌声凝聚心中不变的热爱。随着国…...
WPS中让两列数据合并的方法
有这样一个需求,就是把A列数据和B列数据进行合并(空单元格略过)具体实现效果如图下: 该如何操作呢? 首先在新的一列第一个单元格中输入公式"A1&B1" 然后回车,就出现了两列单元格数据合并的效…...
使用yum为centos系统安装软件以及使用(包含阿里云yum源配置)
centos系统配置阿里云yum源 因为centos7官方停止维护,自带yum源用不了了,所以可以更换成阿里云yum源 方法: 使用root权限执行以下语句 curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo CentOS…...
《深度学习》【项目】OpenCV 发票识别 透视变换、轮廓检测解析及案例解析
目录 一、透视变换 1、什么是透视变换 2、操作步骤 1)选择透视变换的源图像和目标图像 2)确定透视变换所需的关键点 3)计算透视变换的变换矩阵 4)对源图像进行透视变换 5)对变换后的图像进行插值处理 二、轮廓检测…...
linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
