当前位置: 首页 > news >正文

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 &#xff0c;es的服务端也跟着升级到了es8 &#xff0c;而es的客户端7和服务端8 是不兼容的&#xff0c; 客户端es 7使用的是&#xff1a; elasticsearch-rest-high-level-client es 8 升级到&#xf…...

HCIA_IP路由基础问题?

目录 1. 什么是路由&#xff1f;2. 什么是路由器&#xff1f;3. 什么是路由信息&#xff1f;4. 路由器信息和路由表的区别&#xff1f;5. 路由表的生成方式&#xff1f;6.直连路由生效条件是什么&#xff1f;7.Inloopback0是什么接口&#xff1f;8.最优路由选择的原则&#xff…...

(黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式

&#xff08;黑马出品_高级篇_01&#xff09;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和电子地图美化&#xff0c;以及2013版ArcGIS的SHP电子地图设计&#xff0c;是地理信息系统&#xff08;GIS&#xff09;领域中的两个重要话题。下面将分别对这两个主题进行描述。 样图&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1WB4AGsycyBGagVq5…...

BUUCTF-Ezsql1

1.打开靶机 打开第一个链接 2.万能密码 使用万能密码&#xff1a;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、轮播功能 视频监控项目使用过程中&#xff0c;有时需要大屏…...

npm和pnpm安装、更换镜像源

安装pnpm 1 wins 在系统中搜索框 输入“Windos PowerShell”右击“管理员身份运行” 2 输入“set-ExecutionPolicy RemoteSigned”回车,根据提示输入A&#xff0c;回车 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为例进行说明

模块化开发是一种软件设计方法&#xff0c;它将一个大型程序分解成独立的、可以单独开发和测试的模块或组件。这种方法提高了代码的可重用性、可维护性和可测试性。不同编程语言实现模块化开发的方式各有特色&#xff0c;但都遵循基本的设计原则&#xff0c;如封装、接口抽象和…...

外贸网站文章批量生成器

随着全球贸易的不断发展&#xff0c;越来越多的企业开始关注外贸市场&#xff0c;而拥有高质量的内容是吸引潜在客户的关键之一。然而&#xff0c;为外贸网站生产大量优质的文章内容可能是一项耗时且繁琐的任务。因此&#xff0c;外贸网站文章批量生成软件成为了解决这一难题的…...

maven一点通

1.maven简介 Maven是一个基于Java的工程构建工具&#xff0c;用于管理和构建项目的依赖关系。它提供了一种标准的项目结构和一组约定&#xff0c;使得项目的开发、构建、部署和文档化更加容易和可靠。 Maven的主要功能包括&#xff1a; 依赖管理&#xff1a;Maven可以自动下载…...

超越标签的探索:K-means与DBSCAN在数据分析中的新视角

最近在苦恼为我的数据决定分组问题&#xff0c;在查找资料时&#xff0c;恰好看到机器学习中的无监督学习的聚类分析&#xff0c;正好适用于我的问题&#xff0c;但是我之前学机器学习时。正好没有学习无监督部分&#xff0c;因为我认为绝大多数问题都是有标签的监督学习&#…...

linux板子vscode gdb 远程调试

板子&#xff1a;hi3556v200 交叉编译工具&#xff1a;arm-himix200-linux 主机&#xff1a;win10虚拟机的ubuntu16.4 gdb:gdb-8.2.tar.gz 1.在ubuntu交叉编译gdb&#xff08;Remote g packet reply is too long解决&#xff09; 建议修改gdb8.2/gdb目录下面的remote.c解决…...

nginx代理服务器配置

nginx代理服务器配置 需要配置环境需求 1、一台1.1.1.1服务器&#xff0c;一台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 ①&#xff1a;在…...

基于Matlab的视频人面检测识别,Matalb实现

博主简介&#xff1a; 专注、专一于Matlab图像处理学习、交流&#xff0c;matlab图像代码代做/项目合作可以联系&#xff08;QQ:3249726188&#xff09; 个人主页&#xff1a;Matlab_ImagePro-CSDN博客 原则&#xff1a;代码均由本人编写完成&#xff0c;非中介&#xff0c;提供…...

VSCode创建用户代码片段-案例demo

示例 - 在线生成代码片段 Vue3代码片段 {"vue3": {scope": "javascript,typescript,html,vue","prefix": "vue3","body": ["<template>","$1","</template>",""…...

河南大学-数字图像处理-图像变换

计算机与信息工程学院实验报告 序号&#xff1a;20 姓名&#xff1a;__杨馥瑞___ 学号&#xff1a;_2212080042_ 专业&#xff1a;__数据科学与大数据技术 年级&#xff1a;___2022级_____ 课程&#xff1a;数字图像处理 主讲教师&#xff1a;张延锋 辅导教师&#x…...

华为OD七日集训第3期 - 按算法分类,由易到难,循序渐进,玩转OD

目录 一、适合人群二、本期训练时间三、如何参加四、七日集训第 3 期五、精心挑选21道高频100分经典题目&#xff0c;作为入门。第1天、逻辑分析第2天、字符串处理第3天、矩阵第4天、深度优先搜索dfs算法第5天、回溯法第6天、二分查找第7天、图、正则表达式 大家好&#xff0c;…...

Android中的进程间通讯

一、简介 进程间通讯&#xff08;InterProcess Communication&#xff09; 指在不同进程之间传播或交换信息&#xff0c;Android是基于Linux 系统的&#xff0c;在Linux 中进程间是不能直接通讯的&#xff0c;IPC就是为了解决这一问题 每个操作系统都有相应的IPC机制&#x…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

32单片机——基本定时器

STM32F103有众多的定时器&#xff0c;其中包括2个基本定时器&#xff08;TIM6和TIM7&#xff09;、4个通用定时器&#xff08;TIM2~TIM5&#xff09;、2个高级控制定时器&#xff08;TIM1和TIM8&#xff09;&#xff0c;这些定时器彼此完全独立&#xff0c;不共享任何资源 1、定…...

【Java多线程从青铜到王者】单例设计模式(八)

wait和sleep的区别 我们的wait也是提供了一个还有超时时间的版本&#xff0c;sleep也是可以指定时间的&#xff0c;也就是说时间一到就会解除阻塞&#xff0c;继续执行 wait和sleep都能被提前唤醒(虽然时间还没有到也可以提前唤醒)&#xff0c;wait能被notify提前唤醒&#xf…...

C/Python/Go示例 | Socket Programing与RPC

Socket Programming介绍 Computer networking这个领域围绕着两台电脑或者同一台电脑内的不同进程之间的数据传输和信息交流&#xff0c;会涉及到许多有意思的话题&#xff0c;诸如怎么确保对方能收到信息&#xff0c;怎么应对数据丢失、被污染或者顺序混乱&#xff0c;怎么提高…...

codeforces C. Cool Partition

目录 题目简述&#xff1a; 思路&#xff1a; 总代码&#xff1a; https://codeforces.com/contest/2117/problem/C 题目简述&#xff1a; 给定一个整数数组&#xff0c;现要求你对数组进行分割&#xff0c;但需满足条件&#xff1a;前一个子数组中的值必须在后一个子数组中…...