Springboot + elasticsearch + RestHighLevelClient 整合

本文介绍 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);

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值