elasticsearch快速应用于SpringBoot

第一步:导入maven依赖

XML 复制代码
        <!--接入ES-->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.4.0</version>
        </dependency>

第二步:配置配置类

java 复制代码
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.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class EsConfig {


    @Value("${spring.es.addrs.host}")
    private String url;
    @Value("${spring.es.addrs.port}")
    private Integer port;
    @Value("${spring.es.username}")
    private String username;
    @Value("${spring.es.password}")
    private String password;

    @Bean
    @Qualifier("restHighLevelClient")
    public RestHighLevelClient restHighLevelClient(){
        //需要用户名和密码的认证
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
        RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(url, port, "http"))
                .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                    @Override
                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
                        return httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                    }
                });
        return new RestHighLevelClient(restClientBuilder);
    }
}

第三步:工具类准备

java 复制代码
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.core.CountResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author reshui
 * @Description es工具类
 * @Date 2023/9/04
 * @Version 1.0
 */
@Slf4j
@Component
public class EsHandler<T> {

    @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient restHighLevelClient;

    public SearchHit[] search(String indexName, SearchSourceBuilder builder) throws IOException{
        SearchRequest request = new SearchRequest(indexName).source(builder);
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        //SearchHits提供有关所有匹配的全局信息,例如总命中数或最高分数:
        SearchHits hits = response.getHits();
        return hits.getHits();
    }

    public <T> List<T> search(String indexName, SearchSourceBuilder builder,Class<T> clazz,String highlightField) throws IOException{
        SearchRequest request = new SearchRequest(indexName).source(builder);
        long start = System.currentTimeMillis();
        log.info("es 查询开始 ==== index:{} {}",indexName,builder.toString());
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        long end = System.currentTimeMillis();
        log.info("es 查询结束 ==== 命中:{} 耗时:{}",response.getHits().getTotalHits().value,end - start);
        //SearchHits提供有关所有匹配的全局信息,例如总命中数或最高分数:
        SearchHits hits = response.getHits();
        return parseSearchHits(hits.getHits(),clazz,highlightField);
    }

    public long count(String indexName, SearchSourceBuilder builder) throws IOException{
        CountRequest countRequest = new CountRequest(indexName);
        countRequest.source(builder);
        long start = System.currentTimeMillis();
        log.info("es count开始 ==== index:{} {}",indexName,builder.toString());
        CountResponse response = restHighLevelClient.count(countRequest, RequestOptions.DEFAULT);
        long end = System.currentTimeMillis();
        log.info("es count结束 ==== 总量:{} 耗时:{}",response.getCount(),end - start);
        return response.getCount();
    }

    public boolean deleteByIds(String indexName, List<Integer> list) throws IOException{
        //创建批量操作请求
        BulkRequest request = new BulkRequest();
        for (Integer id : list) {
            request.add(new DeleteRequest().index(indexName).id(id.toString()));
        }
        //根据id批量删除es数据
        long start = System.currentTimeMillis();
        log.info("es 删除开始 ==== index:{} 数量:{}",indexName,list.size());
        BulkResponse response = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
        long end = System.currentTimeMillis();
        log.info("es 删除结束 ==== 耗时:{}",end - start);
        return true;
    }

    public boolean updateBulk(String indexName, List<T> list) throws IOException{
        //创建批量操作请求
        BulkRequest request = new BulkRequest();
        for (T t : list) {
            Map<String, Object> map = BeanUtil.beanToMap(t);
            Object id = map.get("id");
            if (id != null){
                request.add(new UpdateRequest().index(indexName).id(map.get("id").toString()).doc(map).docAsUpsert(true));
            }else {
                request.add(new UpdateRequest().index(indexName).doc(map).docAsUpsert(true));
            }
        }
        //根据id批量删除es数据
        long start = System.currentTimeMillis();
        log.info("es 批量更新开始 ==== index:{} 数量:{}",indexName,list.size());
        BulkResponse response = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
        long end = System.currentTimeMillis();
        log.info("es 批量更新结束 ==== 耗时:{}",end - start);
        return true;
    }

    public <T> List<T> parseSearchHits(SearchHit[] hits, Class<T> clazz, String highlightField) throws IOException{
        List<T> list = new ArrayList<>();
        if (hits == null || hits.length == 0){
            return list;
        }
        for (SearchHit hit : hits) {
            //获取到结果的map集合
            Map<String, Object> map = hit.getSourceAsMap();
            //设置高亮
            if (!StringUtils.isEmpty(highlightField)){
                //获取到高亮字段
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                //将高亮字段的具体内容取出来
                HighlightField str = highlightFields.get(highlightField);
                if (str != null) {
                    //得到高亮的字符串内容
                    Text[] fragments = str.fragments();
                    String highlight = "";
                    for (Text fragment : fragments) {
                        highlight += fragment;
                    }
                    //将原本没有高亮的结果集合中的title换为由高亮的
                    map.put(highlightField,highlight);
                }
            }

            //将map集合转换为实体类
            T t = JSON.parseObject(JSON.toJSONString(map), clazz);
            list.add(t);
        }
        return list;
    }


}

第四步:创建索引

java 复制代码
    public boolean createMapping() {
        boolean flag = false;
        try {
            GetIndexRequest indexRequest = new GetIndexRequest(TEST_INDEX);
            boolean exists = client.indices().exists(indexRequest, RequestOptions.DEFAULT);
            if (exists) {
                return true;
            }

            //创建mapping
            XContentBuilder mappings = XContentFactory.jsonBuilder()
                    .startObject()
                    .startObject("properties")
                    .startObject("id").field("type", "long").field("store", true).endObject()

                    .startObject("classIds").field("type", "long").field("store", true).endObject()
                    .startObject("classLevels").field("type", "text").field("store", true).endObject()
                    .startObject("title").field("type", "text").field("store", true).endObject()
                    .endObject()
                    .endObject();

            //设置setting
            XContentBuilder settings = XContentFactory.jsonBuilder()
                    .startObject()
                    .startObject("index").field("max_result_window", 100000).endObject()
                    .endObject();

            //创建索引
            CreateIndexRequest request = new CreateIndexRequest(TEST_INDEX);
            request.mapping(mappings);
            request.settings(settings);
            client.indices().create(request, RequestOptions.DEFAULT);
            flag = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }

第五步:简单的使用方法测试

java 复制代码
import com.eebbk.task.handler.EsHandler;

import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;

/**
 * @author reshui
 * @date 2023/9/4
 **/
@Slf4j
@SpringBootTest
public class EsHandlerTest {

    @Resource
    private EsHandler esHandler;

    private String indexName = "test_index";

    @Test
    void contextLoads() throws IOException {

        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title").field("tag");
        highlightBuilder.preTags("<span style=\"color: red\">");
        highlightBuilder.postTags("</span>");
        SearchSourceBuilder builder = new SearchSourceBuilder().highlighter(highlightBuilder).from(1).size(100);
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("title","*"+"地球的运动"+"*"));
        List<PropertyVo> result = esHandler.search(indexName, builder.query(boolQueryBuilder), PropertyVo.class, title);

        System.out.println(result);
    }
}
相关推荐
paopaokaka_luck12 分钟前
[371]基于springboot的高校实习管理系统
java·spring boot·后端
java1234_小锋36 分钟前
Elasticsearch中的节点(比如共20个),其中的10个选了一个master,另外10个选了另一个master,怎么办?
大数据·elasticsearch·jenkins
Elastic 中国社区官方博客37 分钟前
Elasticsearch 开放推理 API 增加了对 IBM watsonx.ai Slate 嵌入模型的支持
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
我的运维人生37 分钟前
Elasticsearch实战应用:构建高效搜索与分析平台
大数据·elasticsearch·jenkins·运维开发·技术共享
捂月1 小时前
Spring Boot 深度解析:快速构建高效、现代化的 Web 应用程序
前端·spring boot·后端
FIN技术铺4 小时前
Spring Boot框架Starter组件整理
java·spring boot·后端
小码的头发丝、4 小时前
Spring Boot 注解
java·spring boot
午觉千万别睡过4 小时前
RuoYI分页不准确问题解决
spring boot
2301_811274314 小时前
大数据基于Spring Boot的化妆品推荐系统的设计与实现
大数据·spring boot·后端
Mephisto.java5 小时前
【大数据学习 | Spark】Spark的改变分区的算子
大数据·elasticsearch·oracle·spark·kafka·memcache