SpringBoot中elasticsearch7.6.2的集成和使用

1.前言
最近工作没有那么饱和,在测试过程中发现公司搜索功能执行特别慢。查询速度在1.3秒以上,一个简单的搜索要1.3秒是肯定不行的,所以就想到了使用elasticsearch去优化搜索功能。
2.安装配置elasticsearch
。。。。。自行百度,百度上很多安装教程,这里就不过多描述了。
3.SpringBoot集成elasticsearch
首先elasticsearch和SpringBoot版本是有对应关系的,如果不知道怎么看自己的项目版本对应的elasticsearch版本可以在Maven中查看jar包,看jar包版本即可,如下图:
SpringBoot中elasticsearch7.6.2的集成和使用_第1张图片
然后是Maven坐标:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>

3.Java代码中集成es
配置类:其中ip,端口,请求方式可以使用SpringBoot提供的也可以自己写entity去读取配置文件

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author Mr.Du
 * @date 2020/10/26
 */
@Configuration
public class ElasticSearchConfig {
     


    /**
     * restHighLevelClient 相当于spring中的id  RestHighLevelClient相当于class
     */
    @Bean
    public RestHighLevelClient restHighLevelClient() {
     
        return new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("192.168.100.14",9211,"http")));
    }

}

工具类:

import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
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.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author Mr.Du
 * @date 2020/10/26
 */
@Component
public class EsUtil {
     

    @Resource
    private RestHighLevelClient restHighLevelClient;

    private final String STATUS = "OK";

    /**
     * 创建索引
     *
     * @param indexs 索引名称
     * @return true 创建成功,false创建失败
     */
    private boolean createIndex(String... indexs) throws Exception {
     
        for (String index : indexs) {
     
            GetIndexRequest getIndexRequest = new GetIndexRequest(index);
            if (restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT)) {
     
                throw new RuntimeException("索引:" + index + "已存在");
            }
        }
        for (String index : indexs) {
     
            //创建索引请求
            CreateIndexRequest createIndexRequest = new CreateIndexRequest(index);
            //创建执行请求
            CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        }
        return true;
    }

    /**
     * 查看索引是否存在
     *
     * @return true存在 false不存在
     * @throws IOException es连接异常
     */
    private boolean getIndex(String index) throws IOException {
     
        GetIndexRequest getIndexRequest = new GetIndexRequest(index);
        return restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
    }

    /**
     * 删除索引
     *
     * @return true删除成功 false删除失败或索引不存在
     */
    public boolean deleteIndex(String index) {
     
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(index);
        try {
     
            AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
            return true;
        } catch (IOException e) {
     
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 插入数据
     *
     * @param index 索引名称
     * @param data  数据 可以为单个对象也可以为数组
     * @return true 插入成功 false插入失败
     * @throws IOException es连接异常
     */
    public boolean insertData(String index, String id, Object... data) throws Exception {
     
        boolean flag = getIndex(index);
        if (!flag) {
     
            createIndex(index);
        }
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("15s");
        for (int i = 0; i < data.length; i++) {
     
            bulkRequest.add(new IndexRequest(index).id(id).source(JSON.toJSONString(data[i]), XContentType.JSON));
        }
        BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        //是否失败 bulk.hasFailures()=false 代表成功
        return !bulk.hasFailures();
    }

    /**
     * 修改数据
     *
     * @param index 索引
     * @param id    esId
     * @param data  修改后的数据
     * @return true修改成功 false修改失败
     * @throws IOException es连接异常
     */
    public boolean updateData(String index, String id, Object data) throws IOException {
     
        UpdateRequest updateRequest = new UpdateRequest(index, id);
        updateRequest.timeout("1s");
        UpdateRequest doc = updateRequest.doc(JSON.toJSONString(data), XContentType.JSON);
        UpdateResponse update = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
        return STATUS.equals(update.status().toString());
    }

    /**
     * @param index 索引
     * @param id    esId
     * @return true删除成功 false删除失败
     * @throws IOException es连接异常
     */
    public boolean deleteData(String index, String id) throws IOException {
     
        DeleteRequest deleteRequest = new DeleteRequest(index, id);
        deleteRequest.timeout("1s");
        DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
        return STATUS.equals(deleteResponse.status().toString());
    }

    /**
     * 根据分页查询数据 查询全部
     *
     * @param index 索引名称
     * @param form  页数 如果查看第一页传-1
     * @param size  数量 默认传10
     * @return 查询好的SearchHit数组
     * @throws IOException es连接异常
     */
    public SearchHits queryPage(String index, Integer form, Integer size) throws IOException {
     
        SearchRequest searchRequest = new SearchRequest(index);
        //构建搜索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //QueryBuilders.matchAllQuery查询所有
        MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
        searchSourceBuilder.query(matchAllQueryBuilder);
        //构建分页
        if (form == -1) {
     
            searchSourceBuilder.from();
        } else {
     
            searchSourceBuilder.from(form);
        }
        searchSourceBuilder.size(size);
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(searchSourceBuilder);
        SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        return search.getHits();
    }

    /**
     * 精确查找
     *
     * @param index 索引名称
     * @param form  页数 如果查看第一页传-1
     * @param size  数量 默认传10
     * @param name  查询参数名
     * @param value 查询值
     * @return 查询好的SearchHit数组
     * @throws IOException es连接异常
     */
    public SearchHit[] queryPage(String index, Integer form, Integer size, String name, String value) throws IOException {
     
        SearchRequest searchRequest = new SearchRequest(index);
        //构建搜索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //QueryBuilders.termQuery 精确查找
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(name, value);
        searchSourceBuilder.query(termQueryBuilder);
        //构建分页
        if (form == -1) {
     
            searchSourceBuilder.from();
        } else {
     
            searchSourceBuilder.from(form);
        }
        searchSourceBuilder.size(size);
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(searchSourceBuilder);
        SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        return search.getHits().getHits();
    }

    /**
     * PC端模糊搜索用户。手机号,拼音,汉字参数必须有一个不为空
     *
     * @param index  索引
     * @param form   页数 如果查看第一页传-1
     * @param size   数量 默认传10
     * @param mobile 手机号 可以为null
     * @param pinYin 汉字拼音 可以为null
     * @param hanZi  汉字 可以为null
     * @return
     */
    public SearchHit[] queryLikeQuery(String index, Integer form, Integer size, String mobile, String pinYin, String hanZi) throws IOException {
     
        SearchRequest searchRequest = new SearchRequest(index);
        //构建搜索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        multi_match

        //判断是汉字搜索还是拼音搜索还是手机号搜索
        if (hanZi != null) {
     
            //QueryBuilders.multiMatchQuery 模糊查找
            MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(hanZi, "customerName");
            searchSourceBuilder.query(multiMatchQueryBuilder);
        }
        if (mobile != null) {
     
            char[] chars = mobile.toCharArray();
            StringBuilder stringBuilder = new StringBuilder();
            for (char aChar : chars) {
     
                stringBuilder.append(aChar).append(" ");
            }
            MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(stringBuilder.toString(), "customerStrMobile");
            searchSourceBuilder.query(multiMatchQueryBuilder);
        }
        if (pinYin != null) {
     
            char[] chars = pinYin.toCharArray();
            StringBuilder stringBuilder = new StringBuilder();
            for (char aChar : chars) {
     
                stringBuilder.append(aChar).append(" ");
            }
            String[] fieldNames = new String[2];
            fieldNames[0] = "customerNamePYAbbr";
            fieldNames[1] = "customerNamePYAll";
            MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(stringBuilder.toString(), fieldNames);
            searchSourceBuilder.query(multiMatchQueryBuilder);
        }
        //构建分页
        if (form == -1) {
     
            searchSourceBuilder.from();
        } else {
     
            searchSourceBuilder.from(form);
        }
        searchSourceBuilder.size(size);
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(searchSourceBuilder);
        SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        return search.getHits().getHits();
    }
}

4.集成过程中踩到的坑。。
ps:我在使用es的过程中没有使用ik分词器,因为业务可以不适用分词器就可以达成。
先描述下业务场景,我的业务场景很简单就是一个普通的搜索功能,如下图
在这里插入图片描述
涉及到了拼音搜索,首字母搜索,手机号、姓名搜索。
首先是汉字搜索,如下图:
SpringBoot中elasticsearch7.6.2的集成和使用_第2张图片
SpringBoot中elasticsearch7.6.2的集成和使用_第3张图片
但是在拼音及手机号搜索时,他没有办法搜索出值,我猜测的原因应该是他没有将拼音、手机号拆分。于是我在添加数据时我手动将手机号、拼音中加了空格,方便匹配。(其中耗费了整整一天的功夫。。)果然在我拼接过空格以后就可以顺利的查询出值,如下图:
SpringBoot中elasticsearch7.6.2的集成和使用_第4张图片
SpringBoot中elasticsearch7.6.2的集成和使用_第5张图片
其中语句已经在代码中实现,请移步屏幕上拖,看esutil工具类中的queryLikeQuery方法

你可能感兴趣的:(java,springBoot,java,elasticsearch,spring)