Elasticsearch8.18.8 Java API Client实现mysql数据同步到elasticsearch,并可以实现高级搜索高亮显示,提取泛型方法,可以支持多个实体类es数据写入

📅 2026/8/21 8:57:53
Elasticsearch8.18.8 Java API Client实现mysql数据同步到elasticsearch,并可以实现高级搜索高亮显示,提取泛型方法,可以支持多个实体类es数据写入
elasticsearch版本8.18.8同步MySQL数据到elasticsearchimportco.elastic.clients.elasticsearch.ElasticsearchClient;importco.elastic.clients.elasticsearch.indices.CreateIndexRequest;importorg.springframework.beans.BeanUtils;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importjava.io.IOException;importjava.util.List;ServicepublicclassArticleEsServiceImplimplementsIArticleEsService{AutowiredprivateRemoteArticleServiceremoteArticleService;AutowiredprivateElasticsearchClientclient;//elasticsearch新建的索引名privatefinalStringINDEX_NAMEarticle;OverridepublicvoidinitArticleEs()throwsIOException{//删库 保证配置是最新的booleanvalueclient.indices().exists(e-e.index(INDEX_NAME)).value();//存在该库 则删除if(value){client.indices().delete(d-d.index(INDEX_NAME));}//建库 numberOfShards-分片数 numberOfReplicas--副本数量 建立映射//将需要高级搜索的字段放到elasticsearch中并配置分词器CreateIndexRequestrequestCreateIndexRequest.of(r-r.index(INDEX_NAME).settings(s-s.numberOfShards(1).numberOfReplicas(1)).mappings(m-m.properties(id,p-p.long_(l-l)).properties(title,p-p.text(t-t.analyzer(ik_max_word))).properties(subTitle,p-p.text(t-t.analyzer(ik_max_word))).properties(summary,p-p.text(t-t.analyzer(ik_max_word)))));client.indices().create(request);System.out.println(article es 建库成功);//查询mysqlListArticlearticlesremoteArticleService.list(inner).getData();//同步mysql数据到esfor(Articlearticle:articles){ArticleEsarticleEsnewArticleEs();//相同名字的属性进行拷贝BeanUtils.copyProperties(article,articleEs);client.index(i-i.index(INDEX_NAME).id(articleEs.getId().toString()).document(articleEs));}}}高级搜索高亮显示importco.elastic.clients.elasticsearch.ElasticsearchClient;importco.elastic.clients.elasticsearch.core.SearchResponse;importco.elastic.clients.elasticsearch.core.search.Highlight;importco.elastic.clients.elasticsearch.core.search.HighlightField;importco.elastic.clients.elasticsearch.core.search.Hit;importco.elastic.clients.elasticsearch.core.search.HitsMetadata;importorg.apache.commons.beanutils.BeanUtils;AutowiredprivateElasticsearchClientclient;AutowiredprivateRemoteArticleServiceremoteArticleService;//具体实现方法 通过指定的查询条件进行查询privateObjectsearchArticle(SearchQueryquery)throwsIOException,InvocationTargetException,IllegalAccessException{//设置高亮的内容 和 高亮显示的内容样式MapString,HighlightFieldfieldMapnewHashMap();fieldMap.put(title,HighlightField.of(h-h));fieldMap.put(subTitle,HighlightField.of(h-h));fieldMap.put(summary,HighlightField.of(h-h));HighlighthighlightHighlight.of(h-h.fields(fieldMap).preTags(span stylecolor:red).postTags(/span));//获取结果集 设置查询的elasticsearch索引名分页数据字段的查询条件添加高亮设置(不添加默认是em/em包围)SearchResponseArticleEsrespclient.search(s-s.index(article).from((query.getCurrentPage()-1)*query.getPageSize()).size(query.getPageSize()).query(q-q.multiMatch(m-m.fields(title,subTitle,summary).query(query.getKeyword()))).highlight(highlight),ArticleEs.class);//获取到返回的数据集HitsMetadataArticleEshitsresp.hits();//结果数据的总条数longtotalhits.total().value();//结果数据集已高亮显示的内容ListHitArticleEshitListhits.hits();//存放返回的原mysql数据ListArticlearticlesnewArrayList();//遍历拿到的elasticsearch数据结果集for(HitArticleEshit:hitList){//获取到idLongidLong.valueOf(hit.id());//通过id查询对应的MySQL数据内容ArticlearticleremoteArticleService.getOne(id,SecurityConstants.INNER).getData();//返回的高亮数据集进行遍历MapString,ListStringhighlightMaphit.highlight();for(Stringkey:highlightMap.keySet()){//通过stringBuffer进行拼接StringBufferstringBuffernewStringBuffer();highlightMap.get(key).forEach(stringBuffer::append);StringvaluestringBuffer.toString();//进行实体类的复制 通过key更改value值BeanUtils.setProperty(article,key,value);}//放到返回的结果集中articles.add(article);}//设置分页PageablepageablePageRequest.of(query.getCurrentPage()-1,query.getPageSize());//返回高亮查询的结果集returnnewPageImplArticle(articles,pageable,total);}通过泛型实现通用方法es写入在开发中可能不止一个文章实体类的内容需要放入到es中比如笔记、攻略等不同的实体类查询部分代码有冗余可以写成泛型的形式去进行数据的高亮查询接口importorg.springframework.data.domain.Page;importjava.io.IOException;importjava.lang.reflect.InvocationTargetException;publicinterfaceISearchService{/* T表示MySQL中的实体类类型 例Article K表示elasticsearch中索引的类型 例ArticleEs 参数index-es库名 clazz-MySQL中实体类的字节码 esCalzz--es中类的字节码 fields-要查哪些列 */T,KPageTsearchWithHighlight(StringindexName,ClassTclazz,ClassKesCalzz,SearchQueryquery,String...fields)throwsIOException,InvocationTargetException,IllegalAccessException;}实现类importco.elastic.clients.elasticsearch.ElasticsearchClient;importco.elastic.clients.elasticsearch.core.SearchRequest;importco.elastic.clients.elasticsearch.core.SearchResponse;importco.elastic.clients.elasticsearch.core.search.Highlight;importco.elastic.clients.elasticsearch.core.search.HighlightField;importco.elastic.clients.elasticsearch.core.search.Hit;importco.elastic.clients.elasticsearch.core.search.HitsMetadata;importorg.apache.commons.beanutils.BeanUtils;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.domain.Page;importorg.springframework.data.domain.PageImpl;importorg.springframework.data.domain.PageRequest;importorg.springframework.data.domain.Pageable;importorg.springframework.stereotype.Service;importjava.io.IOException;importjava.lang.reflect.Array;importjava.lang.reflect.InvocationTargetException;importjava.util.*;ServicepublicclassSearchServiceImplimplementsISearchService{AutowiredprivateElasticsearchClientclient;//因为是springcloud项目所以通过feign进行调用AutowiredprivateRemoteStrategyServiceremoteStrategyService;AutowiredprivateRemoteNoteServiceremoteNoteService;AutowiredprivateRemoteArticleServiceremoteArticleService;/* 参数 1.es中的索引名 2.MySQL中的实体类 3.对应es中的实体类 4.查询参数 5.es实体类对应的字段数组 */OverridepublicT,KPageTsearchWithHighlight(StringindexName,ClassTclazz,ClassKesCalzz,SearchQueryquery,String...fields)throwsIOException,InvocationTargetException,IllegalAccessException{//高亮配置MapString,HighlightFieldhighlightFieldsnewHashMap();for(Stringfield:fields){highlightFields.put(field,HighlightField.of(h-h));}//设置高亮显示条件HighlighthighlightHighlight.of(h-h.preTags(span stylecolor:red).postTags(/span).fields(highlightFields));//查询条件 分页条件 设置高亮条件并设置分词器SearchResponseKrespclient.search(s-s.index(indexName).from((query.getCurrentPage()-1)*query.getPageSize()).size(query.getPageSize()).query(q-q.multiMatch(m-m.query(query.getKeyword()).fields(Arrays.asList(fields)).analyzer(ik_max_word))).highlight(highlight),esCalzz);//获取到查询的数据集HitsMetadataKhitsresp.hits();//获取到查询到的总条数longtotalhits.total().value();//拿到查询到的数据ListHitKhitListhits.hits();//创建空集合供存入返回数据集ListTresultsnewArrayList();//遍历es查询到的数据将高亮数据写入到MySQL中for(HitKhit:hitList){LongidLong.valueOf(hit.id());Ttnull;//MySQL元数据if(strategy.equals(indexName)){t(T)remoteStrategyService.getOne(id,inner).getData();}elseif(note.equals(indexName)){t(T)remoteNoteService.getOne(id,inner).getData();}elseif(article.equals(indexName)){t(T)remoteArticleService.getOne(id,inner).getData();}//取高亮数据MapString,ListStringhighlightMaphit.highlight();StringBufferbuffernewStringBuffer();SetStringkeySethighlightMap.keySet();for(Stringkey:keySet){//进行数据拼接highlightMap.get(key).forEach(buffer::append);BeanUtils.setProperty(t,key,buffer.toString());}results.add(t);}//添加分页条件PageablepageablePageRequest.of(query.getCurrentPage()-1,query.getPageSize());//返回带有分页条件的数据returnnewPageImpl(results,pageable,total);}}