spring boot集成 elasticsearch集群 之REST Client

elasticsearch 集群的搭建 和 概念这里不说可以参考以下地址:
https://www.cnblogs.com/chenmc/tag/elasticSearch/
,主要记录下,自己工作中要去集成es 时,选用操作es的方式

三种方式

操作es的主要有三种方式:
第一种 :spring date es ,这种方式简单,多用于一些简单业务,但因为方法都帮你封装好了,灵活度不高!(复杂业务不推荐)

第二种 :transportClient ,这种方式,官方已经明确表示在ES 7.0版本中将弃用TransportClient客户端,且在8.0版本中完全移除它

第三种 :REST Client 这种方式是基于http 与 es 通信,方便(官网推荐),主要有restHighLevelClient 和restlowLevelClient俩版本,这里也是我是选用的方式.

依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>esearch</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>esearch</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.1</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


        <!-- Java Low Level REST Client -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>6.3.2</version>
        </dependency>

        <!-- Java High Level REST Client -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>6.3.2</version>
        </dependency>
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>net.minidev</groupId>
            <artifactId>json-smart</artifactId>
            <version>2.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <!--<version>4.3.10.RELEASE</version>-->
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.properties 配置

集群用","连接

elasticSearch.hostlist=127.0.0.1:9201,127.0.0.1:9200
elasticSearch.client.connectNum=10
elasticSearch.client.connectPerRoute=50

配置REST Client

这里配置了restHighLevelClient 和restlowLevelClient 两种 ,因为restHighLevelClient 还有不完善的地方,可以用restlowLevelClient 补充


@Configuration
@ComponentScan(basePackageClasses=ESClientSpringFactory.class)
public class ElasticsearchConfig {

    @Value("${elasticSearch.client.connectNum}")
    private Integer connectNum;

    @Value("${elasticSearch.client.connectPerRoute}")
    private Integer connectPerRoute;

    @Value("${elasticSearch.hostlist}")
    private String hostlist;

    @Bean
    public HttpHost[] httpHost(){
        //解析hostlist配置信息
        String[] split = hostlist.split(",");
        //创建HttpHost数组,其中存放es主机和端口的配置信息
        HttpHost[] httpHostArray = new HttpHost[split.length];
        for(int i=0;i<split.length;i++){
            String item = split[i];
            httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
        }
        return httpHostArray;
    }

    @Bean(initMethod="init",destroyMethod="close")
    public ESClientSpringFactory getFactory(){
        return ESClientSpringFactory.
                build(httpHost(), connectNum, connectPerRoute);
    }

    @Bean
    @Scope("singleton")
    public RestClient getRestClient(){
        return getFactory().getClient();
    }

    @Bean(name = "restHighLevelClient")
    @Scope("singleton")
    public RestHighLevelClient getRHLClient(){
        return getFactory().getRhlClient();
    }

}


配置ESClientSpringFactory

public class ESClientSpringFactory {

    public static int CONNECT_TIMEOUT_MILLIS = 1000;
    public static int SOCKET_TIMEOUT_MILLIS = 30000;
    public static int CONNECTION_REQUEST_TIMEOUT_MILLIS = 500;
    public static int MAX_CONN_PER_ROUTE = 10;
    public static int MAX_CONN_TOTAL = 30;

    private static HttpHost[] HTTP_HOST;
    private RestClientBuilder builder;
    private RestClient restClient;
    private RestHighLevelClient restHighLevelClient;

    private static ESClientSpringFactory esClientSpringFactory = new ESClientSpringFactory();

    private ESClientSpringFactory(){}

    public static ESClientSpringFactory build(HttpHost[] httpHostArray,
                                              Integer maxConnectNum, Integer maxConnectPerRoute){
        HTTP_HOST = httpHostArray;
        MAX_CONN_TOTAL = maxConnectNum;
        MAX_CONN_PER_ROUTE = maxConnectPerRoute;
        return  esClientSpringFactory;
    }

    public static ESClientSpringFactory build(HttpHost[] httpHostArray,Integer connectTimeOut, Integer socketTimeOut,
                                              Integer connectionRequestTime,Integer maxConnectNum, Integer maxConnectPerRoute){
        HTTP_HOST = httpHostArray;
        CONNECT_TIMEOUT_MILLIS = connectTimeOut;
        SOCKET_TIMEOUT_MILLIS = socketTimeOut;
        CONNECTION_REQUEST_TIMEOUT_MILLIS = connectionRequestTime;
        MAX_CONN_TOTAL = maxConnectNum;
        MAX_CONN_PER_ROUTE = maxConnectPerRoute;
        return  esClientSpringFactory;
    }


    public void init(){
        builder = RestClient.builder(HTTP_HOST);
        setConnectTimeOutConfig();
        setMutiConnectConfig();
        restClient = builder.build();
        restHighLevelClient = new RestHighLevelClient(builder);
        System.out.println("init factory");
    }
    // 配置连接时间延时
    public void setConnectTimeOutConfig(){
        builder.setRequestConfigCallback(requestConfigBuilder -> {
            requestConfigBuilder.setConnectTimeout(CONNECT_TIMEOUT_MILLIS);
            requestConfigBuilder.setSocketTimeout(SOCKET_TIMEOUT_MILLIS);
            requestConfigBuilder.setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT_MILLIS);
            return requestConfigBuilder;
        });
    }
    // 使用异步httpclient时设置并发连接数
    public void setMutiConnectConfig(){
        builder.setHttpClientConfigCallback(httpClientBuilder -> {
            httpClientBuilder.setMaxConnTotal(MAX_CONN_TOTAL);
            httpClientBuilder.setMaxConnPerRoute(MAX_CONN_PER_ROUTE);
            return httpClientBuilder;
        });
    }

    public RestClient getClient(){
        return restClient;
    }

    public RestHighLevelClient getRhlClient(){
        return restHighLevelClient;
    }

    public void close() {
        if (restClient != null) {
            try {
                restClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("close client");
    }
}


配置esUtils

public final class SpringBeanUtil
{

    private SpringBeanUtil()
    {
    }

    /**
     * 根据bean名称获取
     * 
     * @param name
     * @return
     */
    public static Object getBean(String name)
    {
        return ApplicationContextRegister.getApplicationContext().getBean(name);
    }

}
@Component
public class ApplicationContextRegister implements ApplicationContextAware {


    private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationContextRegister.class);
    private static ApplicationContext APPLICATION_CONTEXT;

    /**
     * 设置spring上下文  *  * @param applicationContext spring上下文  * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        LOGGER.debug("ApplicationContext registed-->{}", applicationContext);
        APPLICATION_CONTEXT = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return APPLICATION_CONTEXT;
    }
}
public class EsUtils {

    private static RestHighLevelClient client;


    public static RestHighLevelClient getInstance() {
        if (client == null) {
            synchronized (RestHighLevelClient.class) {
                if (client == null) {
                    client = (RestHighLevelClient) SpringBeanUtil.getBean("restHighLevelClient");
                    System.out.println(client);
                }
            }
        }
        return client;
    }


    public static void main(String[] args) {
        getInstance();
    }

    /**
     * 创建索引
     *
     * @param index  索引名称
     * @param type   类型名称,可传入多个type逗号分隔
     * @param arg1   分片数
     * @param arg2   副本数
     * @param source 需要设置的映射(配置是否分词,是否索引等)
     * @return boolean
     */

    public static boolean addIndex(String index, String type, int arg1, int arg2, String source) {
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(index);
        //设置索引参数
        createIndexRequest.settings(Settings.builder().put("number_of_shards", arg1).put("number_of_replicas", arg2));
        //操作索引的客户端
        createIndexRequest.mapping(type, source, XContentType.JSON);

        IndicesClient indices = getInstance().indices();
        //执行创建
        CreateIndexResponse createIndexResponse = null;
        try {
            indices.create(createIndexRequest);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //得到响应
        return true;

    }


    /**
     * 删除索引
     *
     * @param index 索引名称
     * @return boolean
     */
    public static boolean delIndex(String index) throws IOException {
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(index);
        //操作索引的客户端
        IndicesClient indices = getInstance().indices();
        //执行删除
        DeleteIndexResponse deleteIndexResponse = indices.delete(deleteIndexRequest);
        //得到响应
        return deleteIndexResponse.isAcknowledged();
    }

    /**
     * 添加数据
     *
     * @param index      索引名称
     * @param type       类型
     * @param jsonObject json对象(要添加的数据)
     * @return boolean
     */
    public static boolean addDoc(String index, String type, String id, JSONObject jsonObject) {
        //索引请求对象
        IndexRequest indexRequest = new IndexRequest(index, type, id);
        indexRequest.source(jsonObject);
        //索引响应对象
        try {
            getInstance().index(indexRequest);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取响应结果
        return true;
    }

    /**
     * 修改数据
     *
     * @param index      索引名称
     * @param type       类型
     * @param jsonObject json对象(要添加的数据)
     * @param id
     * @return RestStatus ok
     */

    public static boolean updateDoc(String index, String type, JSONObject jsonObject, String id) {
        UpdateRequest updateRequest = new UpdateRequest(index, type, id);
        updateRequest.doc(jsonObject);
        //索引响应对象
        UpdateResponse update = null;
        try {
            getInstance().update(updateRequest);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 删除数据
     *
     * @param index 索引名称
     * @param type  类型
     * @param id    文档id(即某条数据的id)
     * @return RestStatus ok
     */

    public static boolean deleteDoc(String index, String type, String id) {
        DeleteRequest deleteRequest = new DeleteRequest(index, type, id);
        //索引响应对象
        try {
            getInstance().delete(deleteRequest);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }


    /**
     * 使用分词查询
     *
     * @param index     索引名称
     * @param type      类型
     * @param fields    需要显示的字段,逗号分隔(缺省为全部字段)
     * @param query     查询条件
     * @param sortField 排序字段(倒序)
     * @return List<Map < String, Object>>
     */
    public static List<Map<String, Object>> search(String index, String type, String fields, QueryBuilder query, String sortField, String highlightField) {
        //搜索对象
        SearchRequest searchRequest = new SearchRequest(index);
        //设置类型
        searchRequest.types(type);

        //搜索源对象构建
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //搜索条件
        searchSourceBuilder.query(query);

        //设置按字段排序
        if (StringUtils.isNotEmpty(sortField)) {
            searchSourceBuilder.sort(sortField, SortOrder.DESC);
        }
        //过滤字段
        if (StringUtils.isNotEmpty(fields)) {
            searchSourceBuilder.fetchSource(fields.split(","), null);
        }

        return trySearch(searchRequest, searchSourceBuilder, highlightField);

    }


    /**
     * 使用分词查询 并分页
     *
     * @param index          索引名称
     * @param type           类型
     * @param fields         需要显示的字段,逗号分隔(缺省为全部字段)
     * @param query          查询条件
     * @param sortField      排序字段
     * @param highlightField 高亮字段
     * @return List<Map < String, Object>>
     */
    public static List<Map<String, Object>> searchPage(
            String index, String type, String fields, QueryBuilder query,
            String sortField, int size, int page, String highlightField) {
        //搜索对象
        SearchRequest searchRequest = new SearchRequest(index);
        //设置类型
        searchRequest.types(type);

        //搜索源对象构建0
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //计算起始下标
        int from = (page - 1) * size;
        searchSourceBuilder.from(from);//起始下标,从0开始

        searchSourceBuilder.size(size);//每页记录数
        //设置搜索条件
        searchSourceBuilder.query(query);

        //过滤字段
        if (StringUtils.isNotEmpty(fields)) {
            searchSourceBuilder.fetchSource(fields.split(","), null);
        }

        //设置按字段排序
        if (StringUtils.isNotEmpty(sortField)) {
            searchSourceBuilder.sort(sortField, SortOrder.DESC);
        }
        return trySearch(searchRequest, searchSourceBuilder, highlightField);

    }

    /**
     * 进行搜索
     *
     * @param searchRequest
     * @param searchSourceBuilder
     */
    public static List<Map<String, Object>> trySearch(SearchRequest searchRequest, SearchSourceBuilder searchSourceBuilder, String highlightField) {
        //设置搜索源
        searchRequest.source(searchSourceBuilder);

        //设置高亮
        if (StringUtils.isNotEmpty(highlightField)) {
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.preTags("<highlight>");
            highlightBuilder.postTags("</highlight>");
            highlightBuilder.fields().add(new HighlightBuilder.Field(highlightField));
            searchSourceBuilder.highlighter(highlightBuilder);
        }
        //执行搜索
        SearchResponse searchResponse = null;
        try {
            searchResponse = getInstance().search(searchRequest);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //搜索匹配结果
        SearchHits hits = searchResponse.getHits();
        //搜索总记录数
        long totalHits = hits.getTotalHits();
        System.out.println("搜索总记录数=====" + totalHits);
        //匹配度较高的前n的文档
        SearchHit[] searchHits = hits.getHits();

        List<Map<String, Object>> searchList = new ArrayList<>();
        for (SearchHit hit : searchHits) {
            //文档id
            String id = hit.getId();
            //源文档内容
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            //获取源文档需要高亮的字段
            String name = (String) sourceAsMap.get(highlightField);
            //取出高亮字段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (highlightFields != null) {
                //取出name高亮字段
                HighlightField nameField = highlightFields.get(highlightField);
                if (nameField != null) {
                    Text[] fragments = nameField.fragments();
                    StringBuffer stringBuffer = new StringBuffer();
                    for (Text text : fragments) {
                        stringBuffer.append(text);
                    }
                    name = stringBuffer.toString();
                    hit.getSourceAsMap().put(highlightField, name);
                }

            }
            searchList.add(hit.getSourceAsMap());
            System.out.println(name);
        }
        return searchList;
    }


}

测试代码

@RestController
@RequestMapping("/es")
public class TestController {

    @RequestMapping("/search")
    public List<Map<String, Object>> test(){
        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("酒", "name");

        List<Map<String, Object>> search = EsUtils.search("test", "doc", null, multiMatchQueryBuilder, null, "name");
        return search;
    }

    @RequestMapping("/page")
    public List<Map<String, Object>>  aa() {
        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("酒", "name");

        List<Map<String, Object>> aa = EsUtils.searchPage("test", "doc", null, multiMatchQueryBuilder, null, 1,1,"");
        return aa;
    }

    @RequestMapping("/del")
    public void del() throws IOException {
        EsUtils.delIndex("test");
    }

    @RequestMapping("/add")
    public void add() {
        EsUtils.addIndex("test","doc",1,0,"{\n" +
                "   \"properties\": {\n" +
                "   \t   \"id\": {\n" +
                "           \"type\": \"text\"\n" +
                "       },\n" +
                "       \"name\": {\n" +
                "           \"type\": \"text\"\n" +
                "       },\n" +
                "       \"describe\": {\n" +
                "           \"type\": \"text\"\n" +
                "       },\n" +
                "       \"pic\": {\n" +
                "           \"type\": \"text\",\n" +
                "           \"index\": false\n" +
                "       }\n" +
                "   }\n" +
                "}");
    }

    @RequestMapping("/addDoc")
    public void addDoc() {
        //指定索引添加文档
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id", "a");
        jsonObject.put("name", "你的酒馆对我打了样");
        jsonObject.put("describe", "这一首简单的你的酒馆对我打了样....");
        jsonObject.put("pic", "10");
        EsUtils.addDoc("test","doc","1",jsonObject);
    }

    @RequestMapping("/updateDoc")
    public void updateDoc() {
        //指定索引添加文档
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id", "b");
        jsonObject.put("name", "你的酒馆对我打样");
        jsonObject.put("describe", "这一首简单的你的酒馆对我打样....");
        jsonObject.put("pic", "20");
        EsUtils.updateDoc("test","doc",jsonObject,"1");
    }

    @RequestMapping("/delDoc")
    public void delDoc() {
        EsUtils.deleteDoc("test","doc","1");
    }


}

以上代码亲测有效!希望能帮助大家!如果有错误,也希望多多指教!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值