本文介绍 Springboot 2.0.5.RELEASE + elasticsearch 7.4.0 + elasticsearch-rest-high-level-client 7.4.0 的整合
废话不多说直接上代码
maven
<dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>7.4.0</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.4.0</version> </dependency>
Springboot 这个不上了 各位大佬根据自己的版本来
application.yml 配置
elasticsearch :
hostName: xxxx
port: xxxx
userName : xxxxxxx
password: xxxxxxx
ElasticsearchConfig
import lombok.Data; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.impl.client.BasicCredentialsProvider; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
@Configuration @Data public class ElasticsearchConfig { /** * 用户名. */ @Value("${elasticsearch.userName}") private String userName; /** * 密码. */ @Value("${elasticsearch.password}") private String password; /** * 服务器地址. */ @Value("${elasticsearch.hostName}") private String hostName; /** * 服务器端口. */ @Value("${elasticsearch.port}") private Integer port; /** * es 客户端 * @return {@link RestHighLevelClient} */ @Bean(name = "highClient") public RestHighLevelClient restHighLevelClient() { final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(userName, password)); RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(hostName, port)).setHttpClientConfigCallback( httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)); return new RestHighLevelClient(restClientBuilder); } }
封装通用RestHighLevelClient类
import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.delete.DeleteResponse; import org.elasticsearch.action.get.GetRequest; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateResponse; import org.elasticsearch.client.HttpAsyncResponseConsumerFactory; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import java.lang.reflect.Type; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; /** * <p> CustomRestHighLevelClient </p> * * @author 羽毛 * @date 2020/11/4 20:18 */ @Slf4j @Component public class CustomRestHighLevelClient implements AutoCloseable, ApplicationContextAware { /** * 默认超时时间 */ private static long timeOut = 1L; private static final RequestOptions COMMON_OPTIONS; private RestHighLevelClient restHighLevelClient; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // 注入 restHighLevelClient this.restHighLevelClient = applicationContext.getBean(RestHighLevelClient.class); log.info("restHighLevelClient:({})",restHighLevelClient); } static { RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); // 默认缓存限制为100MB,此处修改为30MB。 builder.setHttpAsyncResponseConsumerFactory( new HttpAsyncResponseConsumerFactory .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024)); COMMON_OPTIONS = builder.build(); } @Override public void close() throws Exception { restHighLevelClient.close(); } /** * 单条 插入 * @param chainEsBO ChainEsBO * @param chainIndexEnum chainIndexEnum * @return */ public IndexResponse insert(ChainEsBO chainEsBO,ChainIndexEnum chainIndexEnum) { final String jsonString = JSONObject.toJSONString(chainEsBO); log.info("es(t:{})",jsonString); final IndexRequest indexRequest = new IndexRequest(chainIndexEnum.getIndexName()).source(jsonString, XContentType.JSON); log.info("es(indexRequest:{})",indexRequest.toString()); IndexResponse indexResponse = null; try { log.info("es(restHighLevelClient:{})",restHighLevelClient); log.info("es(COMMON_OPTIONS:{})",COMMON_OPTIONS); indexResponse = restHighLevelClient.index(indexRequest, COMMON_OPTIONS); log.info("es(indexResponse:{})",indexResponse.toString()); } catch (Exception e) { log.error("es(index:{},e:{})添加失败:", chainIndexEnum.getIndexName(), e); return null; } return indexResponse; } /** * 修改单条数据 * @param chainIndexEnum chainIndexEnum * @param chainEsBO chainEsBO * @return */ public UpdateResponse update(ChainIndexEnum chainIndexEnum,ChainEsBO chainEsBO) { UpdateRequest request = new UpdateRequest(chainIndexEnum.getIndexName(), chainEsBO.getId()); String jsonString = JSONObject.toJSONString(chainEsBO); request.upsert(jsonString, XContentType.JSON); //设置超时:等待主分片变得可用的时间 request.timeout(TimeValue.timeValueSeconds(timeOut)); // 刷新 request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); //如果要更新的文档在获取或者索引阶段已被另一操作更改,则重试更新操作的次数 request.retryOnConflict(3); // 禁用noop检测 request.detectNoop(false); // 无论文档是否存在,脚本都必须运行,即如果脚本尚不存在,则脚本负责创建文档。 request.scriptedUpsert(false); // 如果不存在,则表明部分文档必须用作upsert文档。 request.docAsUpsert(false); request.doc(jsonString, XContentType.JSON); //设置在继续更新操作之前必须激活的分片副本的数量。 // request.waitForActiveShards(2); //使用ActiveShardCount方式,可以是ActiveShardCount.ALL,ActiveShardCount.ONE或ActiveShardCount.DEFAULT(默认值) // request.waitForActiveShards(ActiveShardCount.ALL); //同步执行 UpdateResponse updateResponse = null; try { updateResponse = restHighLevelClient.update(request, COMMON_OPTIONS); } catch (Exception e) { log.error("es(index:{},id:{})更新异常:", chainIndexEnum.getIndexName(), chainEsBO.getId(), e); } return updateResponse; } /** * 批量数据插入 * 记录是否有操作失败的数据,请调用(BulkResponse.hasFailures) * @param chainIndexEnum chainIndexEnum * @param chainEsBOList chainEsBOList * @return BulkResponse */ public BulkResponse batchAll(ChainIndexEnum chainIndexEnum,List<ChainEsBO> chainEsBOList) { BulkRequest bulkRequest = new BulkRequest(); IndexRequest indexRequest; for (ChainEsBO chainEsBO : chainEsBOList) { final String jsonString = JSONObject.toJSONString(chainEsBO); indexRequest = new IndexRequest(chainIndexEnum.getIndexName()) .source(jsonString,XContentType.JSON); bulkRequest.add(indexRequest); } BulkResponse bulkResponse = null; try { bulkResponse = restHighLevelClient.bulk(bulkRequest, COMMON_OPTIONS); } catch (Exception e) { log.error("es批量添加失败:", e); } return bulkResponse; } /** * 删除单个数据 * @param chainIndexEnum chainIndexEnum * @param chainEsBO chainEsBO * @return */ public DeleteResponse deleteById(ChainIndexEnum chainIndexEnum,ChainEsBO chainEsBO) { DeleteRequest request = new DeleteRequest(chainIndexEnum.getIndexName(), chainEsBO.getId()); //设置超时:等待主分片变得可用的时间 request.timeout(TimeValue.timeValueMinutes(timeOut)); //同步执行 DeleteResponse deleteResponse = null; try { deleteResponse = restHighLevelClient.delete(request, COMMON_OPTIONS); } catch (Exception e) { log.error("es(index:{},id:{})删除异常:{}", chainIndexEnum.getIndexName(), chainEsBO.getId(), e); } return deleteResponse; } /** * 根据ids批量删除指定信息 * 记录是否有操作失败的数据,请调用(BulkResponse.hasFailures) * @param chainIndexEnum chainIndexEnum * @param ids ids * @return */ public BulkResponse deleteByIds(ChainIndexEnum chainIndexEnum, List<String> ids) { final BulkRequest request = new BulkRequest(); request.timeout(TimeValue.timeValueSeconds(timeOut)); DeleteRequest deleteRequest; for (String id : ids) { deleteRequest = new DeleteRequest(); deleteRequest.index(chainIndexEnum.getIndexName()); deleteRequest.id(id); request.add(deleteRequest); } BulkResponse response = null; try { response = restHighLevelClient.bulk(request, COMMON_OPTIONS); } catch (Exception e) { log.error("es(index:{},ids:{})删除索引异常:{}", chainIndexEnum.getIndexName(), ids.toString(), e); } return response; } /** * 根据Id查询数据 * @param chainIndexEnum * @param chainEsBO * @return */ public ChainEsBO searchById(ChainIndexEnum chainIndexEnum,ChainEsBO chainEsBO) { // 根据ID查询数据 final GetRequest getRequest = new GetRequest().index(chainIndexEnum.getIndexName()).id(chainEsBO.getId()); GetResponse documentFields = null; try { documentFields = restHighLevelClient.get(getRequest, COMMON_OPTIONS); } catch (Exception e) { log.error("es(index:{},id:{})根据文件Id查询异常:{}", chainIndexEnum.getIndexName(), chainEsBO.getId(), e); } if (documentFields == null) { return null; } return JSONObject.parseObject(documentFields.getSourceAsString(), (Type) chainIndexEnum.getClazz()); } /** * 根据条件查询 * @param sourceBuilder sourceBuilder * @param chainIndexEnum chainIndexEnum * @return List<ChainEsBO> */ public List<ChainEsBO> searchList(SearchSourceBuilder sourceBuilder, ChainIndexEnum chainIndexEnum){ SearchResponse search = null; try { final SearchRequest request = new SearchRequest(chainIndexEnum.getIndexName()); sourceBuilder.timeout(TimeValue.timeValueSeconds(timeOut)); request.source(sourceBuilder); search = restHighLevelClient.search(request, COMMON_OPTIONS); } catch (Exception e) { log.error("es(index:{},e:{})根据条件查询异常:", chainIndexEnum.getIndexName(), e); } if (search == null) { return null; } if (RestStatus.OK.getStatus() != search.status().getStatus()) { log.warn("es(index:{})根据条件查询失败(状态码:{})", chainIndexEnum.getIndexName(), search.status().getStatus()); return null; } // 响应数据 final SearchHits hits = search.getHits(); if (hits == null) { return null; } log.info("es(search:{})",search.toString()); return Arrays.stream(hits.getHits()).filter(Objects::nonNull) .map(documentFields -> { ChainEsBO chainEsBO = JSONObject.parseObject(documentFields.getSourceAsString(), (Type) chainIndexEnum.getClazz()); chainEsBO.setId(documentFields.getId()); return chainEsBO; }) .collect(Collectors.toList()); } /** * 查询数据,带分页,且不指定分页启用默认值 * @param sourceBuilder sourceBuilder * @param chainIndexEnum chainIndexEnum * @return CustomEsPage<ChainEsBO> */ public CustomEsPage<ChainEsBO> searchPage(SearchSourceBuilder sourceBuilder, ChainIndexEnum chainIndexEnum) { // 校验参数 if (sourceBuilder == null) { return CustomEsPage.newPageData(); } // 默认第0条开始 if (sourceBuilder.from() < 0) { sourceBuilder.from(0); } // 默认一页展示10条 if (sourceBuilder.size() < 1) { sourceBuilder.size(20); } SearchResponse search = null; try { final SearchRequest request = new SearchRequest(chainIndexEnum.getIndexName()); sourceBuilder.timeout(TimeValue.timeValueSeconds(timeOut)); request.source(sourceBuilder); search = restHighLevelClient.search(request, COMMON_OPTIONS); } catch (Exception e) { log.error("es(index:{})根据条件查询异常:{}", chainIndexEnum.getIndexName(), e); } if (search == null) { return null; } if (RestStatus.OK.getStatus() != search.status().getStatus()) { log.warn("es(index:{})根据条件查询失败(状态码:{})", chainIndexEnum.getIndexName(), search.status().getStatus()); return CustomEsPage.newPageData(); } // 响应数据 final SearchHits hits = search.getHits(); if (hits == null) { return CustomEsPage.newPageData(); } return new CustomEsPage<ChainEsBO>(Arrays.stream(hits.getHits()).filter(Objects::nonNull) .map(documentFields -> { ChainEsBO chainEsBO = JSONObject.parseObject(documentFields.getSourceAsString(), (Type) chainIndexEnum.getClazz()); chainEsBO.setId(documentFields.getId()); return chainEsBO; }) .collect(Collectors.toList()), hits.getTotalHits().value); } }
封装通用ID类(用户查询出来的数据转成实体的父类)
import lombok.Data; import java.io.Serializable; /** * <p> ChainEsBO 超类 </p> * * @author 羽毛 * @date 2020/11/6 17:32 */ @Data public class ChainEsBO implements Serializable { /** * ES唯一标识ID 自动生成 */ private String id; }
封装通用Index类
/** * <p> ES index 枚举 </p> * * @author 羽毛 * @date 2020/11/7 10:21 */ public enum ChainIndexEnum { /** * chain_live_course_chapter 详细信息 */ CHAIN_LIVE_COURSE_CHAPTER("xxxxx_index", ChainLiveCourseChapterPO.class); /** * index 名称 */ private final String indexName; /** * index 对应的 PO 对象Class */ private final Class clazz; public String getIndexName() { return indexName; } public Class getClazz() { return clazz; } ChainIndexEnum(String indexName, Class tClass) { this.indexName = indexName; this.clazz = tClass; } }
查询示例
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); MatchPhraseQueryBuilder matchPhraseQueryBuilder = null; // 条件 course_id 类似mysql in course_id 可以赋值多个 BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); BoolQueryBuilder childBoolQueryBuilder = new BoolQueryBuilder(); for (Long courseId : datLiveCourseParam.getCourseIds()) { matchPhraseQueryBuilder = QueryBuilders .matchPhraseQuery("course_id", courseId); childBoolQueryBuilder.should(matchPhraseQueryBuilder); } // 条件 uid matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("uid",datLiveCourseParam.getUserId()); boolQueryBuilder .must(QueryBuilders.rangeQuery("create_time").from(datLiveCourseParam.getStartTime().getTime()) .to(datLiveCourseParam.getEndTime().getTime())) .must(childBoolQueryBuilder) .must(matchPhraseQueryBuilder); sourceBuilder.query(boolQueryBuilder); List<ChainEsBO> chainEsBoList = customRestHighLevelClient.searchList(sourceBuilder,this.getChainIndexEnum());
批量新增示例
List<ChainEsBO> chainEsBoList = new ArrayList<>(); ChainLiveCourseChapterPO chainLiveCourseChapterPo = null; for (ChainLiveCourseChapterDTO chainLiveCourseChapterDto: chainLiveCourseChapterDtoList) { chainLiveCourseChapterPo = new ChainLiveCourseChapterPO(); BeanUtils.copyProperties(chainLiveCourseChapterDto, chainLiveCourseChapterPo); if (null == chainLiveCourseChapterPo.getCreateTime()) { chainLiveCourseChapterPo.setCreateTime(new Date()); } chainEsBoList.add(chainLiveCourseChapterPo); } BulkResponse bulkResponse = customRestHighLevelClient.batchAll(this.getChainIndexEnum(),chainEsBoList); if (!bulkResponse.status().equals(RestStatus.OK)) { return 0; }
新增示例
IndexResponse indexResponse = customRestHighLevelClient.insert(chainUserLoginTimePo,this.getChainIndexEnum());
修改示例
UpdateResponse updateResponse = customRestHighLevelClient.update(this.getChainIndexEnum(),chainUserLoginTimePo);