当前位置: 首页 > 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…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...