ElasticSearch回顾3-SpirngBoot整合ElasticSearch

134 阅读5分钟

ElasticSearch回顾3-SpirngBoot整合ES

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

本篇我们熟悉一下ES在Java中的操作,并将ES整合在SpringBoot中

首先贴官网API地址

www.elastic.co/guide/cn/el…

API创建索引及文档

去官网找一圈

www.elastic.co/guide/index…

找到Elasticsearch Clients(这个就是客户端api文档)

image-20201021090133835

这里我们用JavaRest风格的API,我们可以根据自己的语言环境来选择不同的API

image-20201021090209112

选择Java后,我们又发现Java分了两种

image-20201021090246453

一种是high level 和 low level,我们选择high level下的Getting started

image-20201021090408224

找到Maven依赖和基本配置

image-20201021090502635

关于Java Rest Client的说明

Java REST Client 有两种风格:

Java Low Level REST Client :用于Elasticsearch的官方低级客户端。它允许通过http与Elasticsearch 集群通信。将请求编排和响应反编排留给用户自己处理。它兼容所有的Elasticsearch版本。(PS:学过 WebService的话,对编排与反编排这个概念应该不陌生。可以理解为对请求参数的封装,以及对响应结 果的解析)

Java High Level REST Client :用于Elasticsearch的官方高级客户端。它是基于低级客户端的,它提供 很多API,并负责请求的编排与响应的反编排。(PS:就好比是,一个是传自己拼接好的字符串,并且 自己解析返回的结果;而另一个是传对象,返回的结果也已经封装好了,直接是对象,更加规范了参数 的名称以及格式,更加面对对象一点) (PS:所谓低级与高级,我觉得一个很形象的比喻是,面向过程编程与面向对象编程)

项目整合

新建项目

新建一个SpringBoot项目,导入web依赖和elastic依赖

image-20201021090722305

如果忘了也没关系,在pom中加入即可

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

因为SpringBoot默认的配置版本不匹配,我们要自己手动配置自己的ES版本

<elasticsearch.version>7.8.0</elasticsearch.version>

image-20201021091033296

继续查看文档API,

image-20201021091110842

我们发现这里要我们构建一个RestHighLevel的对象,那就整吧

image-20201021091129170

创建配置类

image-20201021093311280

ElasticsearchClientConfig.java

package com.feng.util;

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

/**
 * <h3>springboot-elasticsearch-test</h3>
 * <p></p>
 *
 * @author : Nicer_feng
 * @date : 2020-10-21 09:13
 **/
@Configuration
public class ElasticsearchClientConfig {

    @Bean
    public RestHighLevelClient restHighLevelClient(){
        RestClientBuilder restClientBuilder;
        RestHighLevelClient client = new RestHighLevelClient(
        RestClient.builder(
                new HttpHost("127.0.0.1",9200,"http")));
        return client;
    }

}

ESUtil.java

package com.feng.util;

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.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.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.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <h3>springboot-elasticsearch-test</h3>
 * <p></p>
 *
 * @author : Nicer_feng
 * @date : 2020-10-21 09:19
 **/
public class ESUtils<T> {
    @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient client;
    /**
     * 判断索引是否存在
     * @param index
     * @return
     * @throws IOException
     */
    public boolean existsIndex(String index) throws IOException {
        GetIndexRequest request = new GetIndexRequest(index);
        boolean exists = client.indices().exists(request,
                RequestOptions.DEFAULT);
        return exists;
    }
    /**
     * 删除索引
     * @param index
     * @return
     * @throws IOException
     */
    public boolean deleteIndex(String index) throws IOException {
        DeleteIndexRequest deleteIndexRequest = new
                DeleteIndexRequest(index);
        AcknowledgedResponse response =
                client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
        return response.isAcknowledged();
    }
    /**
     * 判断某索引下文档id是否存在
     * @param index
     * @param id
     * @return
     * @throws IOException
     */
    public boolean docExists(String index, String id) throws IOException {
        GetRequest getRequest = new GetRequest(index,id);
//只判断索引是否存在不需要获取_source
        getRequest.fetchSourceContext(new FetchSourceContext(false));
        getRequest.storedFields("_none_");
        boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
        return exists;
    }
    /**
     * 添加文档记录
     * @param index
     * @param id
     * @param t 要添加的数据实体类
     * @return
     * @throws IOException
     */
    public boolean addDoc(String index,String id,T t) throws IOException {
        IndexRequest request = new IndexRequest(index);
        request.id(id);
        //timeout
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        request.source(JSON.toJSONString(t), XContentType.JSON);
        IndexResponse indexResponse = client.index(request,
                RequestOptions.DEFAULT);
        RestStatus Status = indexResponse.status();
        return Status==RestStatus.OK||Status== RestStatus.CREATED;
    }

    /**
     * 根据id来获取记录
     * @param index
     * @param id
     * @return
     * @throws IOException
     */
    public GetResponse getDoc(String index, String id) throws IOException {
        GetRequest request = new GetRequest(index,id);
        GetResponse getResponse = client.get(request,
                RequestOptions.DEFAULT);
        return getResponse;
    }
    /**
     * 批量添加文档记录
     * 没有设置id ES会自动生成一个,如果要设置 IndexRequest的对象.id()即可
     * @param index
     * @param list
     * @return
     * @throws IOException
     */
    public boolean bulkAdd(String index, List<T> list) throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
//timeout
        bulkRequest.timeout(TimeValue.timeValueMinutes(2));
        bulkRequest.timeout("2m");
        for (int i =0;i<list.size();i++){
            bulkRequest.add(new IndexRequest(index)
                    .source(JSON.toJSONString(list.get(i))));
        }
        BulkResponse bulkResponse = client.bulk(bulkRequest,
                RequestOptions.DEFAULT);
        return !bulkResponse.hasFailures();
    }
    /**
     * 批量删除和更新就不写了可根据上面几个方法来写
     */
    /**
     * 更新文档记录
     * @param index
     * @param id
     * @param t
     * @return
     * @throws IOException
     */
    public boolean updateDoc(String index,String id,T t) throws IOException
    {
        UpdateRequest request = new UpdateRequest(index,id);
        request.doc(JSON.toJSONString(t));
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        UpdateResponse updateResponse = client.update(
                request, RequestOptions.DEFAULT);
        return updateResponse.status()==RestStatus.OK;
    }
    /**
     * 删除文档记录
     * @param index
     * @param id
     * @return
     * @throws IOException
     */
    public boolean deleteDoc(String index,String id) throws IOException {
        DeleteRequest request = new DeleteRequest(index,id);
//timeout
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        DeleteResponse deleteResponse = client.delete(
                request, RequestOptions.DEFAULT);
        return deleteResponse.status()== RestStatus.OK;
    }
    /**
     * 根据某字段来搜索
     * @param index
     * @param field
     * @param key 要收搜的关键字
     * @throws IOException
     */
    public void search(String index,String field ,String key,Integer
            from,Integer size) throws IOException {
        SearchRequest searchRequest = new SearchRequest(index);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termQuery(field, key));
    //控制搜素
        sourceBuilder.from(from);
        sourceBuilder.size(size);
    //最大搜索时间。
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest,
                RequestOptions.DEFAULT);
        System.out.println(JSON.toJSONString(searchResponse.getHits()));
    }
}

这里注意pom中导入alibaba的fastjson类

		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.74</version>
        </dependency>

测试

然后我们测试创建索引

创建索引

package com.feng;

import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
class SpringbootElasticsearchTestApplicationTests {

    @Autowired
    RestHighLevelClient restHighLevelClient;


    @Test
    void contextLoads() throws IOException {
        //1、索引创建
        CreateIndexRequest request = new CreateIndexRequest("feng_index1");
        //2、执行请求 ==> 请求后获取响应
        CreateIndexResponse createIndexResponse
                = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
        System.out.println(createIndexResponse);
    }



}

成功运行并创建索引

image-20201021093557609

image-20201021093609022

获取索引

@Test
    void testExistsIndex() throws IOException {
        GetIndexRequest request = new GetIndexRequest("feng_index1");
        boolean exists = restHighLevelClient.indices().exists(request,
                RequestOptions.DEFAULT);
        System.out.println(exists);
    }

测试存在

image-20201021093719481

删除索引

@Test
    void testDeleteIndexRequest() throws IOException {
        DeleteIndexRequest deleteIndexRequest = new
                DeleteIndexRequest("feng_index1");
        AcknowledgedResponse response
                = restHighLevelClient.indices().delete(deleteIndexRequest,
                RequestOptions.DEFAULT);
        System.out.println(response.isAcknowledged());
    }

测试,返回true,且刷新后 feng_index1消失

image-20201021093826826

如果我们要添加文档记录呢?

添加文档

首先创建一个实体类

User.java

package com.feng.dao;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * <h3>springboot-elasticsearch-test</h3>
 * <p></p>
 *
 * @author : Nicer_feng
 * @date : 2020-10-21 13:45
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
public class User {
    private String name;
    private int age;

}

lombok插件别再问了

测试类

@Test
    void testAddDocument() throws IOException {
        // 创建对象
        User user = new User("冯半仙", 6);
        // 创建请求
        IndexRequest request = new IndexRequest("feng_index1");
        // 规则
        request.id("1");
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        request.source(JSON.toJSONString(user), XContentType.JSON);
        // 发送请求
        IndexResponse indexResponse = restHighLevelClient.index(request,
                RequestOptions.DEFAULT);
        System.out.println(indexResponse.toString());
        RestStatus Status = indexResponse.status();
        System.out.println(Status == RestStatus.OK || Status ==
                RestStatus.CREATED);
    }

运行成功发现

image-20201021135100968

判断索引下文档id是否存在

// 判断此id是否存在这个索引库中
    @Test
    void testIsExists() throws IOException {
        GetRequest getRequest = new GetRequest("feng_index1","1");
        // 不获取_source上下文 storedFields
        getRequest.fetchSourceContext(new FetchSourceContext(false));
        getRequest.storedFields("_none_");
        // 判断此id是否存在!
        boolean exists = restHighLevelClient.exists(getRequest,
                RequestOptions.DEFAULT);
        System.out.println(exists);
    }

查询1和2分别返回结果true和false

GIF 2020-10-21 13-53-19

根据id查询记录

// 获得文档记录
@Test
void testGetDocument() throws IOException {
    GetRequest getRequest = new GetRequest("feng_index1","1");
    GetResponse getResponse = restHighLevelClient.get(getRequest,
            RequestOptions.DEFAULT);
    System.out.println(getResponse.getSourceAsString()); // 打印文档内容
    System.out.println(getResponse);
}

运行结果

image-20201021135612146

更新文档记录

// 更新文档记录
@Test
void testUpdateDocument() throws IOException {
    UpdateRequest request = new UpdateRequest("feng_index1","1");
    request.timeout(TimeValue.timeValueSeconds(1));
    request.timeout("1s");
    User user = new User("冯半仙996", 18);
    request.doc(JSON.toJSONString(user), XContentType.JSON);
    UpdateResponse updateResponse = restHighLevelClient.update(
            request, RequestOptions.DEFAULT);
    System.out.println(updateResponse.status() == RestStatus.OK);
}

当然更新成功

image-20201021135720348

删除文档记录

// 删除文档测试
@Test
void testDelete() throws IOException {
    DeleteRequest request = new DeleteRequest("feng_index1","3");
    //timeout
    request.timeout(TimeValue.timeValueSeconds(1));
    request.timeout("1s");
    DeleteResponse deleteResponse = restHighLevelClient.delete(
            request, RequestOptions.DEFAULT);
    System.out.println(deleteResponse.status() == RestStatus.OK);
}

记得先插一个3,再删除哈

GIF 2020-10-21 13-59-04

批量添加数据

// 批量添加数据
@Test
void testBulkRequest() throws IOException {
    BulkRequest bulkRequest = new BulkRequest();
    //timeout
    bulkRequest.timeout(TimeValue.timeValueMinutes(2));
    bulkRequest.timeout("2m");
    ArrayList<User> userList = new ArrayList<>();
    userList.add(new User("feng1",3));
    userList.add(new User("feng2",3));
    userList.add(new User("feng3",3));
    userList.add(new User("banxian1",3));
    userList.add(new User("banxian2",3));
    userList.add(new User("banxian3",3));
    for (int i =0;i<userList.size();i++){
        bulkRequest
                .add(new IndexRequest("feng_index1")
                        .id(""+(i+1))
                        .source(JSON.toJSONString(userList.get(i)),XContentType.JSON));
    }
    // bulk
    BulkResponse bulkResponse =
            restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
    System.out.println(!bulkResponse.hasFailures());
}

运行后发现数据成功插入

image-20201021140256051

查询测试

// 查询测试
/**
 * 使用QueryBuilder
 * termQuery("key", obj) 完全匹配
 * termsQuery("key", obj1, obj2..) 一次匹配多个值
 * matchQuery("key", Obj) 单个匹配, field不支持通配符, 前缀具高级特性
 * multiMatchQuery("text", "field1", "field2"..); 匹配多个字段, field有通
 配符忒行
 * matchAllQuery(); 匹配所有文件
 */


@Test
void testSearch() throws IOException {
    SearchRequest searchRequest = new SearchRequest("feng_index1");
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    // TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name","qinjiang1");
    MatchAllQueryBuilder matchAllQueryBuilder =
            QueryBuilders.matchAllQuery();
    sourceBuilder.query(matchAllQueryBuilder);
    sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
    searchRequest.source(sourceBuilder);
    SearchResponse response = restHighLevelClient.search(searchRequest,
            RequestOptions.DEFAULT);
    System.out.println(JSON.toJSONString(response.getHits()));
    System.out.println("================SearchHit==================");
    for (SearchHit documentFields : response.getHits().getHits()) {
        System.out.println(documentFields.getSourceAsMap());
    }
}

运行后

image-20201021140421254