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();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/438156.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

薄膜凸起和开裂是同一种应力导致的吗?

知识星球里的学员问&#xff1a;我们产线上薄膜出了质量问题&#xff0c;都一概归结为应力过大。麻烦讲讲应力的种类&#xff0c;以及不同种类的应力会造成哪些薄膜问题&#xff1f; 内应力的种类&#xff1f; 内应力的分类很多&#xff0c;如果我们按作用的效果来分&#xff…

树莓派 AI 摄像头(Raspberry Pi AI Camera)教程

系列文章目录 前言 人们使用 Raspberry Pi 产品构建人工智能项目的时间几乎与我们生产 Raspberry Pi 的时间一样长。随着我们发布功能越来越强大的设备&#xff0c;我们能够支持的原生应用范围也在不断扩大&#xff1b;但无论哪一代产品&#xff0c;总会有一些工作负载需要外部…

嵌入式外设应用(代码)

文章目录 1. 工业自动化2. 智能家居设备3. 汽车电子4. 生命体征监测仪5. 物联网应用 嵌入式外设应用广泛&#xff0c;有很多应用领域&#xff1a; 1. 工业自动化 应用场景&#xff1a;使用传感器监测设备状态&#xff0c;控制电机的启动和停止。 示例代码&#xff1a; #inc…

Stream流的终结方法(二)——collect

1.Stream流的终结方法 2. collect方法 collect方法用于收集流中的数据放到集合中去&#xff0c;可以将流中的数据放到List&#xff0c;Set&#xff0c;Map集合中 2.1 将流中的数据收集到List集合中 package com.njau.d10_my_stream;import java.util.*; import java.util.f…

SSL VPN | Easyconnect下载安装使用 (详尽)

EasyConnect是一款远程连接工具&#xff0c;为用户提供简便、快捷的远程访问和控制解决方案。 目录 下载 安装 使用 卸载 下载 通过链接进入官网技术支持板块 深信服技术支持-简单、高效、自助化服务 (sangfor.com.cn)https://support.sangfor.com.cn/ 选择软件下载 在安…

ElasticSearch学习笔记(三)Ubuntu 2204 server elasticsearch集群配置

如果你只是学习elasticsearch的增、删、改、查等相关操作&#xff0c;那么在windows上安装一个ES就可以了。但是你如果想在你的生产环境中使用Elasticsearch提供的强大的功能&#xff0c;那么还是建议你使用Linux操作系统。 本文以在Ubuntu 2204 server中安装elasticsearch 8.…

Redis:hash类型

Redis&#xff1a;hash类型 hash命令设置与读取HSETHGETHMGET 哈希操作HEXISTSHDELHKEYSHVALSHGETALLHLENHSETNXHINCRBYHINCRBYFLOAT 内部编码ziplisthashtable 目前主流的编程语言中&#xff0c;几乎都提供了哈希表相关的容器&#xff0c;Redis自然也会支持对应的内容&#xf…

【Godot4.3】用2D网格模拟一点透视

概述 空间的透视是可以在二维平面上参数化计算和模拟的。本篇基于CanvasItem绘制函数draw_colored_polygon()自带的UV坐标和贴图功能&#xff0c;实现基础的平行透视效果。 或者可以叫做一点透视&#xff0c;由一个消失点决定物体的透视效果。 测试代码 extends Node2Dvar re…

【课程学习】Wireless Communications

Goldsmith A. Wireless communications[M]. Cambridge university press, 2005. Wireless Communications 无线通信课程 文章目录 2-Path Loss, Shadowing, and Multipath2.4-Two-Ray Multipath Model时延扩展 delay spread P33 3-Statistical Multipath Channel Models3.3-Wid…

HarmonyOS应用六之应用程序进阶一

目录&#xff1a; 1、UIAbility的冷启动和UIAbility热启动2、静态资源和动态资源的访问3、页面跳转3.1、页面返回跳转 4、HAR的ArkUI组件、接口、资源&#xff0c;供其他应用或当前应用的其他模块引用4.1、导出HAR的ArkUI组件4.2、引用HAR的ArkUI组件 5、循环渲染6、状态管理最…

【MySQL】多表联合查询常见练习题

数据库表如下&#xff1a; teacher&#xff1a;老师表 course&#xff1a;课程表 student&#xff1a;学生表 class&#xff1a;班级表 sc&#xff1a;成绩表 一、根据上面5张表写sql语句 1. 查询” 01 “课程比” 02 “课程成绩高的学生的信息及课程分数 select student.…

在Ubuntu 20.04中安装CARLA

0. 引言 CARLA (Car Learning to Act) 是一款开源自动驾驶模拟器&#xff0c;其支持自动驾驶系统全管线的开发、训练和验证&#xff08;Development, Training, and Validation of autonomous driving systems&#xff09;。Carla提供了丰富的数字资产&#xff0c;例如城市布局…

国外电商系统开发-运维系统功能清单开发

一、最终效果图 二、功能清单 功能 描述 自定义日志绘图 根据Nginx、Apache登录日志文件绘图&#xff0c;绘图数据包括&#xff1a;访问量走势&#xff0c;500错误&#xff0c;200正确百分比等 创建服务器 加入服务器 主机状态自动检查 加入主机到系统后&#xff0c;系统…

MyBatis——ORM

MyBatis——ORM 验证映射配置ResultType本质是ResultMap具体的转换逻辑 概括的说&#xff0c;MyBatis中&#xff0c;对于映射关系的声明是由开发者在xml文件手动完成的。比如对查询方法而言&#xff0c;你需要显式声明ResultType或ResultMap&#xff0c;这里其实就是在定义数据…

(16)MATLAB仿真Nakagami-m分布1

文章目录 前言一、Nakagami分布二、MATLAB建模代码三、仿真结果画图四、总结 前言 Nakagami衰落模型最初是由于该模型与短波电离层传播的经验结果相匹配而提出的。它还用于仿真来自多个干扰源的情况&#xff0c;因为多个独立且同分布&#xff08;i.i.d&#xff09;的瑞利分布随…

基于四种网络结构的WISDM数据集仿真及对比:Resnet、LSTM、Shufflenet及CNN

在上节中&#xff0c;我们已经详细介绍了WISDM数据集及如何使用CNN网络训练&#xff0c;得到了六个维度的模型仿真指标及五个维度的可视化分析&#xff0c;那么现在我们将训练模型推广到其他网路结构中去&#xff0c;通过仿真实验来对比一下不同网络之间对于WISDM数据集的训练效…

大语言模型入门(三)——提示词编写注意事项

一、提示词编写原则 提示词的编写应当遵循两个原则&#xff0c; 一个是指令必须清晰且具体&#xff0c;另一个是应当给模型充足的时间去思考。首先&#xff0c;你的指令足够清晰和具体&#xff0c;才能让大模型明确你需要它执行的任务&#xff0c;从而降低我们得到无关或者不正…

kubernetes-强制删除命名空间

一、故障现象 1、删除命名空间卡住、强制删除也卡住 2、其他终端显示命名空间下无资源 二、处理步骤 1、kubectl get namespace cilium-test -o json > temp.json 获取你需要删除的命名空间json描述文件。 2、修改finalize字段 3、替换 kubectl replace --raw "/api/v1…

Pikachu-xss防范措施 - href输出 js输出

总体原则&#xff1a; 输入做过滤&#xff0c;输出做转义 过滤&#xff1a;根据业务需要进行过滤&#xff0c;如&#xff1a;输入点要求输入手机号&#xff0c;则只允许输入手机号格式的数字&#xff1b; 转义&#xff1a;所有输出到前端的数据&#xff0c;都根据输出点进行转…

【MySQL】DML数据操作语句和基本的DQL语句

目录 一、Mysql对数据的增删改 1. 增加数据 2. 修改数据&#xff08;UPDATE语句&#xff09; 3. 删除 3.1 delete、truncate、drop区别 二、DQL语言&#xff08;重点&#xff09; 1. 单表查询 1.1 最简单的查询 1.2 从表中获取数据 1.3 字段名起别名 1.4 添加字段 1…