elasticsearch-java api 8 升级 📅 发布时间:2026/9/14 19:29:54 👁 浏览次数: es client api 升级背景公司项目从sring-boot2升级到了spring-boot3es的服务端也跟着升级到了es8 而es的客户端7和服务端8 是不兼容的客户端es 7使用的是elasticsearch-rest-high-level-clientes 8 升级到elasticsearch-java两者之间查询api的变化还是比较大的也花了不少时间在这个修改上所以记录下中间的切换姿势仅供大家参考升级过程依赖调整!--es7 版本客户端 --!-- dependency--!-- groupIdcom.baibu.platform/groupId--!-- artifactIdka-order-server-interface/artifactId--!-- version7.1.0/version--!-- /dependency--!--es8 版本客户端 --dependencygroupIdco.elastic.clients/groupIdartifactIdelasticsearch-java/artifactIdversion8.10.4/version/dependency查询api代码调整参考官方文档 https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/getting-started-java.html创建clientDataAccessors(chaintrue)publicstaticclassESProperties{privateListNodenodes;privateStringusername;privateStringpasswd;DataAccessors(chaintrue)publicstaticclassNode{privateStringhost;privateIntegerport;privateStringscheme;}BeanConfigurationProperties(elasticsearch)publicESPropertiesesProperty(){returnnewESProperties();}BeanpublicElasticsearchClientelasticsearchClient(ESPropertiesesProperties){HttpHost[]httpHostsnewHttpHost[esProperties.getNodes().size()];// 这里配置你的es服务端hostfor(inti0;iesProperties.getNodes().size();i){ESProperties.NodenodeesProperties.getNodes().get(i);HttpHosthttpHostnewHttpHost(node.getHost(),node.getPort(),node.getScheme());httpHosts[i]httpHost;}//RestClientrestClientRestClient.builder(httpHosts).setHttpClientConfigCallback(httpClientBuilder-{CredentialsProvidercredentialsProvidernewBasicCredentialsProvider();// 这里是设置服务端账户密码没有可以不用credentialsProvider.setCredentials(AuthScope.ANY,newUsernamePasswordCredentials(esProperties.getUsername(),esProperties.getPasswd()));httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);returnhttpClientBuilder;}).build();ElasticsearchTransporttransportnewRestClientTransport(restClient,newJacksonJsonpMapper());// And create the API clientElasticsearchClientelasticsearchClientnewElasticsearchClient(transport);returnelasticsearchClient;}查询api// 构建boolqueryBoolQuery.BuilderboolQueryBuilderQueryBuilders.bool()// must wildcard 模糊查询boolQueryBuilder.must(query-query.wildcard(t-t.field(wildcard).value(*1111)));// terms 多个值匹配ListStringlist;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)));SearchRequestsearchRequestSearchRequest.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是keySearchResponseMapelasticsearchClient.search(searchRequest,Map.class)ListLongidsearchResponse.hits().hits().stream().map(e-e.source().get(id)).collect(Collectors.toList());当然你也可以参考官网的方式 一个Query 一个Query 的must个人觉得不是很方便tring searchTextbike;doublemaxPrice200.0;// Search by product nameQuerybyNameMatchQuery.of(m-m.field(name).query(searchText))._toQuery();// Search by max priceQuerybyMaxPriceRangeQuery.of(r-r.field(price).gte(JsonData.of(maxPrice)))._toQuery();// Combine name and price queries to search the product indexSearchResponseProductresponseesClient.search(s-s.index(products).query(q-q.bool(b-b.must(byName).must(byMaxPrice))),Product.class);// 获取查询结果ListHitProducthitsresponse.hits().hits();for(HitProducthit:hits){Productproducthit.source();logger.info(Found product product.getSku(), score hit.score());}聚合统计// Aggregation 统计 terms 字段每个值和对应值的数量也可以统计avg 、interval、等AggregationaggregationAggregationBuilders.terms(terms-terms.field(terms));SearchRequestsearchRequestSearchRequest.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));SearchResponsesearchResponseelasticsearchClient.search(searchRequest,Map.class);// 获取统计结果Aggregateterms(Aggregate)searchResponse.aggregations().get(aggregations);searchTypeList.lterms().buckets().array().forEach(e-{longquantitye.docCount();Stringkeye.key()});注解方式上面的方式很繁琐每增加一个条件都需要我们手动设置条件查询语句我们可以通过在字段上加上自定义注解的方式 去生成对用的查询条件主要逻辑如下 源码放在github 大家自取 https://github.com/Rfruelu/es-search-api-generator/** * 查询模式 */publicenumEsQueryMode{TERM,TERMS,WILDCARD,RANGE,}/** * 通用转换 * * author LuTshoes * version 1.0 */publicclassGeneralConvertHandlerimplementsIConvertHandler{/** * 将注解和对象转换为BoolQuery * * param annotation 注解 * param o 对象 * return 转换后的BoolQuery */OverridepublicBoolQueryconvert(Annotationannotation,Objecto){// 判断注解是否为GeneralConvert类型并且对象不为空if(annotationinstanceofGeneralConvertObjects.nonNull(o)){// 获取注解的key值Stringkey((GeneralConvert)annotation).key();// 获取注解的查询模式EsQueryModemode((GeneralConvert)annotation).mode();// 使用switch语句根据查询模式执行不同的逻辑switch(mode){caseTERM:// 如果查询模式是TERM则构建BoolQuery对象添加term查询条件returnQueryBuilders.bool().must(t-t.term(f-f.field(key).value(FieldValue.of(JsonData.of(o))))).build();caseTERMS:// 如果查询模式是TERMS并且对象是集合类型if(oinstanceofCollection){// 将对象转换为集合Collection?collection(Collection?)o;// 将集合中的每个元素转换为FieldValue对象并构建成列表ListFieldValuefieldValuescollection.stream().map(c-FieldValue.of(JsonData.of(c))).collect(Collectors.toList());// 构建BoolQuery对象添加terms查询条件returnQueryBuilders.bool().must(t-t.terms(f-f.field(key).terms(v-v.value(fieldValues)))).build();}break;caseWILDCARD:// 如果查询模式是WILDCARD则构建BoolQuery对象添加wildcard查询条件returnQueryBuilders.bool().must(t-t.wildcard(f-f.field(key).value(*o*))).build();caseRANGE:// 如果查询模式是RANGE并且对象是EsRangeObject类型if(oinstanceofEsRangeObject){// 将对象转换为EsRangeObject类型EsRangeObjectrangeObject(EsRangeObject)o;// 创建RangeQuery.Builder对象设置查询的字段RangeQuery.BuilderrangeQueryBuilders.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查询条件returnQueryBuilders.bool().must(range.build()._toQuery()).build();}break;default:// 如果查询模式不匹配任何已知模式则不执行任何操作break;}}// 如果注解不是GeneralConvert类型或者对象为空则返回nullreturnnull;}}/** * description: 通用转换 */DocumentedRetention(RetentionPolicy.RUNTIME)Target({ElementType.TYPE,ElementType.FIELD})publicinterfaceGeneralConvert{/** * 获取键值 * * return 返回键值 */Stringkey();/** * 获取当前ES查询模式 * * return 返回当前ES查询模式 */EsQueryModemode();}DataAccessors(chaintrue)publicclassLuTshoesextendsAbstractEsConditionReqDto{GeneralConvert(keyterm,modeEsQueryMode.TERM)privateStringterm;GeneralConvert(keyterms,modeEsQueryMode.TERMS)privateListStringterms;GeneralConvert(keywildcard,modeEsQueryMode.WILDCARD)privateStringwildcard;GeneralConvert(keyrangeObject,modeEsQueryMode.RANGE)privateEsRangeObjectrangeObject;publicstaticvoidmain(String[]args)throwsIllegalAccessException{LuTshoesluTshoesnewLuTshoes().setTerm(term).setRangeObject(newEsRangeObject().setFrom(100).setTo(200)).setWildcard(123456).setTerms(List.of(terms,2));System.out.println(luTshoes.build());}OverridepublicBoolQuerybuild()throwsIllegalAccessException{// 也可以自己定义实现returnBoolQueryAdapter.convert(this);}}