elasticsearch-java api 8 升级
es client api 升级
背景
公司项目从sring-boot2 升级到了spring-boot3 ,es的服务端也跟着升级到了es8 ,而es的客户端7和服务端8 是不兼容的,
客户端es 7使用的是: elasticsearch-rest-high-level-client
es 8 升级到: elasticsearch-java
两者之间查询api的变化还是比较大的,也花了不少时间在这个修改上,所以记录下中间的切换姿势,仅供大家参考
升级过程
依赖调整
<!--es7 版本客户端 -->
<!-- <dependency>-->
<!-- <groupId>com.baibu.platform</groupId>-->
<!-- <artifactId>ka-order-server-interface</artifactId>-->
<!-- <version>7.1.0</version>-->
<!-- </dependency>--><!--es8 版本客户端 --><dependency><groupId>co.elastic.clients</groupId><artifactId>elasticsearch-java</artifactId><version>8.10.4</version></dependency>
查询api代码调整
参考官方文档: https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/getting-started-java.html
创建client
@Beanpublic ElasticsearchClient elasticsearchClient(ESProperties esProperties) {HttpHost[] httpHosts = new HttpHost[esProperties.getNodes().size()];// 这里配置你的es服务端hostfor (int i = 0; i < esProperties.getNodes().size(); i++) {ESProperties.Node node = esProperties.getNodes().get(i);HttpHost httpHost = new HttpHost(node.getHost(), node.getPort(), node.getScheme());httpHosts[i] = httpHost;}// RestClient restClient = RestClient.builder(httpHosts).setHttpClientConfigCallback(httpClientBuilder -> {CredentialsProvider credentialsProvider = new BasicCredentialsProvider();// 这里是设置服务端账户,密码,没有可以不用credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(esProperties.getUsername(), esProperties.getPasswd()));httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);return httpClientBuilder;}).build();ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());// And create the API clientElasticsearchClient elasticsearchClient = new ElasticsearchClient(transport);return elasticsearchClient;}
查询api
// 构建boolquery
BoolQuery.Builder boolQueryBuilder = QueryBuilders.bool();
// must wildcard 模糊查询
boolQueryBuilder.must(query -> query.wildcard(t -> t.field("wildcard").value("*" + "1111")));
// terms 多个值匹配List<String> list ;boolQueryBuilder.must(query -> query.terms(t -> t.field("terms").terms(s -> s.value(.stream().map(FieldValue::of).collect(Collectors.toList())))));
// term 匹配boolQueryBuilder.must(query -> query.term(t -> t.field("term").value(111)));// rang 范围 查询boolQueryBuilder.must(query -> query.range(t -> t.field("range").gte(JsonData.of("格式化的日期".replaceFirst(" ", "T")))));
// nested 嵌套查询
boolQueryBuilder.must(query -> query.nested(nestedQuery -> nestedQuery.query(wildcardQuery -> wildcardQuery.range(t -> t.field("nested.wildcardQuery").gte(JsonData.of("格式化的日期".replaceFirst(" ", "T"))))).scoreMode(ChildScoreMode.None).path("nested")));SearchRequest searchRequest = SearchRequest.of(s -> s// 要查询的索引名.index(vo.getIndex())// 查询 条件.query(q -> q.bool(boolQueryBuilder.build())// 分页).from((vo.getPageNum() - 1) * vo.getPageSize()).size(vo.getPageSize())// 排序字段 .sort(sorts.stream().map(sort -> SortOptions.of(a -> a.field(f -> f.field(sort.getSortColumn()).order(sort.getSortType())))).collect(Collectors.toList()))// 查询结果包含哪些字段.source(source -> source.filter(f -> f.includes(Arrays.stream(vo.getInclude()).toList()).excludes("")))); // 这里可以打印es查询 Query DSL ,可以复制到es 控制台验证查询结果log.info("ES搜索引擎分页请求参数={}", searchRequest.toString());
// 获取查询结果 返回结果是一个map ,id是key
SearchResponse<Map> elasticsearchClient.search(searchRequest, Map.class)List<Long> id = searchResponse.hits().hits().stream().map(e -> e.source().get("id")).collect(Collectors.toList());
当然你也可以参考官网的方式 一个Query 一个Query 的must,个人觉得不是很方便
tring searchText = "bike";
double maxPrice = 200.0;// Search by product name
Query byName = MatchQuery.of(m -> m .field("name").query(searchText)
)._toQuery(); // Search by max price
Query byMaxPrice = RangeQuery.of(r -> r.field("price").gte(JsonData.of(maxPrice))
)._toQuery();// Combine name and price queries to search the product index
SearchResponse<Product> response = esClient.search(s -> s.index("products").query(q -> q.bool(b -> b .must(byName) .must(byMaxPrice))),Product.class
);// 获取查询结果
List<Hit<Product>> hits = response.hits().hits();
for (Hit<Product> hit: hits) {Product product = hit.source();logger.info("Found product " + product.getSku() + ", score " + hit.score());
}
聚合统计
// Aggregation 统计 terms 字段每个值和对应值的数量,也可以统计avg 、interval、等
Aggregation aggregation = AggregationBuilders.terms(terms -> terms.field("terms"));SearchRequest searchRequest = SearchRequest.of(s -> s.index("索引name"))// 查询条件.query(q -> q.bool(vo.getBoolQuery()))// 聚合条件 这里 aggregation 也可以通过lambda 自定义 a -> a.histogram(h -> h.field("price").interval(50.0)).aggregations("aggregations",aggregation));SearchResponse searchResponse = elasticsearchClient.search(searchRequest, Map.class);
// 获取统计结果Aggregate terms = (Aggregate) searchResponse.aggregations().get("aggregations");searchTypeList.lterms().buckets().array().forEach(e -> {long quantity = e.docCount();String key= e.key();});
注解方式
上面的方式很繁琐,每增加一个条件都需要我们手动设置条件查询语句,我们可以通过在字段上加上自定义注解的方式 去生成对用的查询条件
主要逻辑如下: 源码放在github ,大家自取 https://github.com/Rfruelu/es-search-api-generator
/*** 查询模式*/
public enum EsQueryMode {TERM,TERMS,WILDCARD,RANGE,
}
/*** 通用转换** @author LuTshoes* @version 1.0*/
public class GeneralConvertHandler implements IConvertHandler {/*** 将注解和对象转换为BoolQuery** @param annotation 注解* @param o 对象* @return 转换后的BoolQuery*/@Overridepublic BoolQuery convert(Annotation annotation, Object o) {// 判断注解是否为GeneralConvert类型并且对象不为空if (annotation instanceof GeneralConvert && Objects.nonNull(o)) {// 获取注解的key值String key = ((GeneralConvert) annotation).key();// 获取注解的查询模式EsQueryMode mode = ((GeneralConvert) annotation).mode();// 使用switch语句根据查询模式执行不同的逻辑switch (mode) {case TERM:// 如果查询模式是TERM,则构建BoolQuery对象,添加term查询条件return QueryBuilders.bool().must(t -> t.term(f -> f.field(key).value(FieldValue.of(JsonData.of(o))))).build();case TERMS:// 如果查询模式是TERMS,并且对象是集合类型if (o instanceof Collection) {// 将对象转换为集合Collection<?> collection = (Collection<?>) o;// 将集合中的每个元素转换为FieldValue对象,并构建成列表List<FieldValue> fieldValues = collection.stream().map(c -> FieldValue.of(JsonData.of(c))).collect(Collectors.toList());// 构建BoolQuery对象,添加terms查询条件return QueryBuilders.bool().must(t -> t.terms(f -> f.field(key).terms(v -> v.value(fieldValues)))).build();}break;case WILDCARD:// 如果查询模式是WILDCARD,则构建BoolQuery对象,添加wildcard查询条件return QueryBuilders.bool().must(t -> t.wildcard(f -> f.field(key).value("*" + o + "*"))).build();case RANGE:// 如果查询模式是RANGE,并且对象是EsRangeObject类型if (o instanceof EsRangeObject) {// 将对象转换为EsRangeObject类型EsRangeObject rangeObject = (EsRangeObject) o;// 创建RangeQuery.Builder对象,设置查询的字段RangeQuery.Builder range = QueryBuilders.range().field(key);// 如果EsRangeObject的from属性不为空,则添加gte查询条件Optional.ofNullable(rangeObject.getFrom()).ifPresent(from -> range.gte(JsonData.of(from)));// 如果EsRangeObject的to属性不为空,则添加lte查询条件Optional.ofNullable(rangeObject.getTo()).ifPresent(to -> range.lte(JsonData.of(to)));// 构建BoolQuery对象,添加range查询条件return QueryBuilders.bool().must(range.build()._toQuery()).build();}break;default:// 如果查询模式不匹配任何已知模式,则不执行任何操作break;}}// 如果注解不是GeneralConvert类型或者对象为空,则返回nullreturn null;}}
/*** @description: 通用转换*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface GeneralConvert {/*** 获取键值** @return 返回键值*/String key();/*** 获取当前ES查询模式** @return 返回当前ES查询模式*/EsQueryMode mode();}
@Data
@Accessors(chain = true)
public class LuTshoes extends AbstractEsConditionReqDto{@GeneralConvert(key = "term", mode = EsQueryMode.TERM)private String term;@GeneralConvert(key = "terms", mode = EsQueryMode.TERMS)private List<String> terms;@GeneralConvert(key = "wildcard", mode = EsQueryMode.WILDCARD)private String wildcard;@GeneralConvert(key = "rangeObject", mode = EsQueryMode.RANGE)private EsRangeObject rangeObject;public static void main(String[] args) throws IllegalAccessException {LuTshoes luTshoes = new LuTshoes().setTerm("term").setRangeObject(newEsRangeObject().setFrom("100").setTo("200")).setWildcard("123456").setTerms(List.of("terms","2"));System.out.println(luTshoes.build());}@Overridepublic BoolQuery build() throws IllegalAccessException {// 也可以自己定义实现return BoolQueryAdapter.convert(this);}
}相关文章:
elasticsearch-java api 8 升级
es client api 升级 背景 公司项目从sring-boot2 升级到了spring-boot3 ,es的服务端也跟着升级到了es8 ,而es的客户端7和服务端8 是不兼容的, 客户端es 7使用的是: elasticsearch-rest-high-level-client es 8 升级到…...
HCIA_IP路由基础问题?
目录 1. 什么是路由?2. 什么是路由器?3. 什么是路由信息?4. 路由器信息和路由表的区别?5. 路由表的生成方式?6.直连路由生效条件是什么?7.Inloopback0是什么接口?8.最优路由选择的原则ÿ…...
(黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
(黑马出品_高级篇_01)SpringCloudRabbitMQDockerRedis搜索分布式 微服务技术——保护 今日目标1.初识Sentinel1.1.雪崩问题及解决方案1.2.服务保护技术对比1.3.Sentinel介绍和安装1.3.1.初识Sentinel1.3.2.安装Sentinel 1.…...
高架学习笔记之信息系统分类概览
目录 零、前言 一、业务处理系统(TPS) 概念 功能 特点 二、管理信息系统(MIS) 概念 功能 组成 三、决策支持系统(DSS) 概念 功能 特点 组成 1. 数据仓库 2. 数据挖掘工具 3. 决策模型 4. 可视化界面 四、专家系统(ES) 概念 特点 组成 求解过程 专家系统…...
2023新版mapinfo美化电子地图 新版2013Arcgis shp电子地图 下载
2023新版MapInfo和电子地图美化,以及2013版ArcGIS的SHP电子地图设计,是地理信息系统(GIS)领域中的两个重要话题。下面将分别对这两个主题进行描述。 样图: 链接:https://pan.baidu.com/s/1WB4AGsycyBGagVq5…...
BUUCTF-Ezsql1
1.打开靶机 打开第一个链接 2.万能密码 使用万能密码:a or 1 # 密码为随意 第二个用kali打开 3.ssh连接靶机 ssh ctf284490d0-7600-4c65-9160-5ced02f45633.node5.buuoj.cn -p 28191 由题可知密码为123456 4.找到并修改index.php文件 找到index.php文件 #内容如…...
LiveGBS流媒体平台GB/T28181功能-大屏播放上大屏支持轮巡播放分屏轮巡值守播放监控视频轮播大屏轮询播放轮播
LiveGBS支持-大屏播放上大屏支持轮巡播放分屏轮巡值守播放监控视频轮播大屏轮询播放轮播 1、轮播功能2、分屏展示3、选择轮播通道4、配置轮播间隔(秒)5、点击开始轮播6、轮播停止及全屏7、搭建GB28181视频直播平台 1、轮播功能 视频监控项目使用过程中,有时需要大屏…...
npm和pnpm安装、更换镜像源
安装pnpm 1 wins 在系统中搜索框 输入“Windos PowerShell”右击“管理员身份运行” 2 输入“set-ExecutionPolicy RemoteSigned”回车,根据提示输入A,回车 3 输入 pnpm -v 查看版本 如果没有版本好就是没有安装 pnpm 输入安装命令 npm install -g pnpm 4 再次 …...
springcloud 复习day1~[自动装配]
package com.gavin.eureka_server;public class First {private String auto"自动装配";public String getAuto() {return auto;}public void setAuto(String auto) {this.auto auto;} }package com.gavin.eureka_server;public class Second { }装配:实现ImportSe…...
模块化开发在不同编程语言中的实现方式有何异同?并以LabVIEW为例进行说明
模块化开发是一种软件设计方法,它将一个大型程序分解成独立的、可以单独开发和测试的模块或组件。这种方法提高了代码的可重用性、可维护性和可测试性。不同编程语言实现模块化开发的方式各有特色,但都遵循基本的设计原则,如封装、接口抽象和…...
外贸网站文章批量生成器
随着全球贸易的不断发展,越来越多的企业开始关注外贸市场,而拥有高质量的内容是吸引潜在客户的关键之一。然而,为外贸网站生产大量优质的文章内容可能是一项耗时且繁琐的任务。因此,外贸网站文章批量生成软件成为了解决这一难题的…...
maven一点通
1.maven简介 Maven是一个基于Java的工程构建工具,用于管理和构建项目的依赖关系。它提供了一种标准的项目结构和一组约定,使得项目的开发、构建、部署和文档化更加容易和可靠。 Maven的主要功能包括: 依赖管理:Maven可以自动下载…...
超越标签的探索:K-means与DBSCAN在数据分析中的新视角
最近在苦恼为我的数据决定分组问题,在查找资料时,恰好看到机器学习中的无监督学习的聚类分析,正好适用于我的问题,但是我之前学机器学习时。正好没有学习无监督部分,因为我认为绝大多数问题都是有标签的监督学习&#…...
linux板子vscode gdb 远程调试
板子:hi3556v200 交叉编译工具:arm-himix200-linux 主机:win10虚拟机的ubuntu16.4 gdb:gdb-8.2.tar.gz 1.在ubuntu交叉编译gdb(Remote g packet reply is too long解决) 建议修改gdb8.2/gdb目录下面的remote.c解决…...
nginx代理服务器配置
nginx代理服务器配置 需要配置环境需求 1、一台1.1.1.1服务器,一台2.2.2.2服务器 前端包路径在1.1.1.1 /etc/dist 下 后端服务在2.2.2.2 上 暴露端口为9999 2、需求 现在需要访问 1.1.1.1:80访问到2.2.2.2 上面的9999后端服务 3、配置nginx ①:在…...
基于Matlab的视频人面检测识别,Matalb实现
博主简介: 专注、专一于Matlab图像处理学习、交流,matlab图像代码代做/项目合作可以联系(QQ:3249726188) 个人主页:Matlab_ImagePro-CSDN博客 原则:代码均由本人编写完成,非中介,提供…...
VSCode创建用户代码片段-案例demo
示例 - 在线生成代码片段 Vue3代码片段 {"vue3": {scope": "javascript,typescript,html,vue","prefix": "vue3","body": ["<template>","$1","</template>",""…...
河南大学-数字图像处理-图像变换
计算机与信息工程学院实验报告 序号:20 姓名:__杨馥瑞___ 学号:_2212080042_ 专业:__数据科学与大数据技术 年级:___2022级_____ 课程:数字图像处理 主讲教师:张延锋 辅导教师&#x…...
华为OD七日集训第3期 - 按算法分类,由易到难,循序渐进,玩转OD
目录 一、适合人群二、本期训练时间三、如何参加四、七日集训第 3 期五、精心挑选21道高频100分经典题目,作为入门。第1天、逻辑分析第2天、字符串处理第3天、矩阵第4天、深度优先搜索dfs算法第5天、回溯法第6天、二分查找第7天、图、正则表达式 大家好,…...
Android中的进程间通讯
一、简介 进程间通讯(InterProcess Communication) 指在不同进程之间传播或交换信息,Android是基于Linux 系统的,在Linux 中进程间是不能直接通讯的,IPC就是为了解决这一问题 每个操作系统都有相应的IPC机制&#x…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
