SpringBoot+Elasticsearch实战

一、引入依赖

本文使用的SpringBoot版本为2.5.4,elasticsearch版本为7.15.0

1. pom文件如下

<?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 https://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.5.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.yh</groupId>
    <artifactId>es-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>es-demo</name>
    <description>es-demo</description>
    <properties>
        <java.version>1.8</java.version>
        <elasticsearch.version>7.15.0</elasticsearch.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--使用的rest-high-level-client-->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>${elasticsearch.version}</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>${elasticsearch.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.70</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2. application.yml配置如下

elasticsearch:
  host-arr:
    - 127.0.0.1:9200

二、ES SpringBoot配置

1. 配置ES服务器地址

package com.yh.esdemo.config;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;


/**
 * @author : yh
 * @date : 2021/8/30 20:35
 */
@Component
@Getter
@Setter
@ConfigurationProperties(prefix = "elasticsearch")
public class EsHostConfig {

    private String[] hostArr;

}

2. 配置RestHighLevelClient

package com.yh.esdemo.config;

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

/**
 * 定义RestClient Bean
 *
 * @author : yh
 * @date : 2021/8/30 20:32
 */
@Configuration
public class EsRestClientConfig {

    @Autowired
    private EsHostConfig esHostConfig;

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        String[] hostArr = esHostConfig.getHostArr();
        int size = hostArr.length;
        HttpHost[] httpHostArr = new HttpHost[size];
        for (int i = 0; i < size; i++) {
            String[] split = hostArr[i].split(":");
            httpHostArr[i] = new HttpHost(split[0], Integer.parseInt(split[1]), "http");
        }
        return new RestHighLevelClient(RestClient.builder(httpHostArr));
    }
    
}

配置完成后只需在相关业务中注入RestHighLevelClient即可使用

三、ES基本使用

索引操作

1. 创建索引
    @Test
    public void addIndex() throws Exception {
        //获取 IndicesClient ,用于创建 Index
        IndicesClient indices = restHighLevelClient.indices();
        //定义一个 CreateIndexRequest ,参数为索引的名称
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("yh_customer");
        //CreateIndexRequest配置相关参数 number_of_shards:分片数  number_of_replicas:每个分片的副本数
        createIndexRequest.settings(
                Settings.builder()
                        .put("index.number_of_shards", 1)
                        .put("index.number_of_replicas", 0)
        );
        Map<String, Object> name = new HashMap<>();
        name.put("type", "text");
        name.put("analyzer", "ik_max_word");//指定分词器
        name.put("search_analyzer", "ik_smart");
        Map<String, Object> timestamp = new HashMap<>();
        timestamp.put("type", "date");
        timestamp.put("format", "yyyy-MM-dd HH:mm:ss");//指定时间格式
        Map<String, Object> uuid = new HashMap<>();
        uuid.put("type", "keyword");
        Map<String, Object> properties = new HashMap<>();
        properties.put("name", name);
        properties.put("timestamp", timestamp);
        properties.put("uuid", uuid);
        Map<String, Object> mapping = new HashMap<>();
        mapping.put("properties", properties);
        //创建mapping  mapping可以理解为此索引中数据的数据结构
        createIndexRequest.mapping(mapping);
        //创建索引 此方法同步返回结果  异步使用 createAsync
        CreateIndexResponse createIndexResponse = indices.create(createIndexRequest, RequestOptions.DEFAULT);
        //创建结果(true/false)
        System.out.println(createIndexResponse.isAcknowledged());
        //输出创建成功的索引名称
        System.out.println(createIndexResponse.index());
    }

最终输出:
16352546351035

2. 删除索引
    @Test
    public void delIndex() throws Exception {
        IndicesClient indices = restHighLevelClient.indices();
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("yh_customer");
        AcknowledgedResponse deleteIndexResponse = indices.delete(deleteIndexRequest, RequestOptions.DEFAULT);
        System.out.println(deleteIndexResponse.isAcknowledged());
    }

增删改查

1. 添加数据(单个)
    @Test
    public void addDoc() throws Exception {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String timestamp = simpleDateFormat.format(new Date());
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("uuid", "534523dqw4qweq24324");
        jsonMap.put("name", "张三");
        jsonMap.put("timestamp", timestamp);
        //创建 IndexRequest 指定id
        IndexRequest indexRequest = new IndexRequest("yh_customer").id("1").source(jsonMap);
        IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        System.out.println(indexResponse);
    }

最终输出:
16352570339401

2. 批量添加数据
    @Test
    public void bulkTest() {
        //批量添加使用 BulkRequest
        BulkRequest bulkRequest = new BulkRequest();
        for (int i = 0; i < 100; i++) {
            Customer customer = new Customer(UUID.randomUUID().toString().replace("-", ""), i + "号客户", LocalDateTime.now());
            //String data = JSONObject.toJSONString(customer);
            String data = JSONObject.toJSONStringWithDateFormat(customer, "yyyy-MM-dd HH:mm:ss");
            IndexRequest request = new IndexRequest("yh_customer").source(data, XContentType.JSON);
            bulkRequest.add(request);
        }
        //同步
//        try {
//            BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
//            boolean hasFailures = bulk.hasFailures();
//            if (hasFailures) {
//                List<BulkItemResponse> collect = Arrays.stream(bulk.getItems()).filter(BulkItemResponse::isFailed).collect(Collectors.toList());
//                System.out.println(collect.size());
//                String msg = bulk.buildFailureMessage();
//                System.out.println(msg);
//            }
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

        //异步
        restHighLevelClient.bulkAsync(bulkRequest, RequestOptions.DEFAULT, new ActionListener<BulkResponse>() {
            //成功回调
            @Override
            public void onResponse(BulkResponse bulkItemResponses) {
                System.out.println("success");
            }

            //失败回调
            @Override
            public void onFailure(Exception e) {
                System.out.println("failure");
                e.printStackTrace();
            }
        });

        try {
            TimeUnit.MINUTES.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

最终输出:
16352575817746

3. 修改数据
    @Test
    public void updateDoc() throws Exception {
        UpdateRequest updateRequest = new UpdateRequest("yh_customer", "1");
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("name", "李四");
        updateRequest.doc(jsonMap);
        UpdateResponse update = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
        System.out.println(update);
    }

最终输出:
16352577179296

4. 获取数据
    @Test
    public void get() throws Exception {
        GetRequest getRequest = new GetRequest("yh_customer");
        getRequest.id("1");
        GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
        System.out.println(getResponse);
    }

最终输出:
16352579192385

5. 直接获取source
    @Test
    public void getSource() throws Exception {
        GetSourceRequest getRequest = new GetSourceRequest("yh_customer", "1");
        GetSourceResponse source = restHighLevelClient.getSource(getRequest, RequestOptions.DEFAULT);
        System.out.println(source);
    }

最终输出:
16352580418359

判断是否存在

    @Test
    public void exists() throws Exception {
        GetRequest getRequest = new GetRequest("yh_customer");
        getRequest.id("1");
        boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
        System.out.println(exists);
    }

最终输出:
16352578138427

四、ES简单搜索

根据条件搜索

    @Test
    public void search() throws Exception {
        SearchRequest searchRequest = new SearchRequest("yh_customer");//没有参数,查询所有索引
        //构建搜索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //根据name字段搜索
        searchSourceBuilder.query(QueryBuilders.matchQuery("name", "1"));
        searchRequest.source(searchSourceBuilder);
        SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //返回命中数据
        SearchHits hits = search.getHits();
        for (SearchHit hit : hits.getHits()) {
            String sourceAsString = hit.getSourceAsString();
            Customer customer = JSONObject.parseObject(sourceAsString, Customer.class);
            System.out.println(customer);
        }
    }

最终输出:
16352583920483

查询所有

    @Test
    public void simpleSearch() throws Exception {
        //创建搜索request
        SearchRequest searchRequest = new SearchRequest("bank");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());//检索所有字段
        SearchRequest request = searchRequest.source(searchSourceBuilder);
        SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        SearchHits hits = search.getHits();//命中条数
        System.out.println("总条数:" + hits.getTotalHits().value);
        for (SearchHit hit : hits) {//默认只检索出10条
            Staff staff = JSONObject.parseObject(hit.getSourceAsString(), Staff.class);
            System.out.println(staff);
        }
    }

最终输出:
16353396396063

五、ES聚合搜索

需要先导入官方提供的测试数据(使用kibana)

    @Test
    public void aggSearch() throws Exception {
        //创建搜索request
        SearchRequest searchRequest = new SearchRequest("bank");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //查询条件
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        //统计各个年龄的平均工资
        searchSourceBuilder.aggregation(AggregationBuilders.terms("ageAgg").field("age").subAggregation(AggregationBuilders.avg("balanceAvgAgg").field("balance")));
        //所有人平均工资
        searchSourceBuilder.aggregation(AggregationBuilders.avg("allBalanceAvgAgg").field("balance"));
        //构建request
        SearchRequest request = searchRequest.source(searchSourceBuilder);
        //search
        SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        //Aggregations aggregations = searchResponse.getAggregations();
        //Aggregation接口有很多实现类  Avg(平均值)
//        Avg avg = aggregations.get("balanceAgg");
//        System.out.println(avg.getValue());
        Aggregations aggregations = searchResponse.getAggregations();
        Terms ageAgg = aggregations.get("ageAgg");
        List<? extends Terms.Bucket> buckets = ageAgg.getBuckets();
        for (Terms.Bucket bucket : buckets) {//只查出了10条数据
            System.out.println("年龄:" + bucket.getKey());
            System.out.println("人数:" + bucket.getDocCount());
            Avg avg = bucket.getAggregations().get("balanceAvgAgg");
            System.out.println("平均工资:" + avg.getValue());
            System.out.println("=================================");
        }
        Avg avg = aggregations.get("allBalanceAvgAgg");
        System.out.println("所有人平均工资:" + avg.getValue());
    }

最终输出:

年龄:31
人数:61
平均工资:28312.918032786885
=================================
年龄:39
人数:60
平均工资:25269.583333333332
=================================
年龄:26
人数:59
平均工资:23194.813559322032
=================================
年龄:32
人数:52
平均工资:23951.346153846152
=================================
年龄:35
人数:52
平均工资:22136.69230769231
=================================
年龄:36
人数:52
平均工资:22174.71153846154
=================================
年龄:22
人数:51
平均工资:24731.07843137255
=================================
年龄:28
人数:51
平均工资:28273.882352941175
=================================
年龄:33
人数:50
平均工资:25093.94
=================================
年龄:34
人数:49
平均工资:26809.95918367347
=================================
所有人平均工资:25714.837

demo地址:https://github.com/yangh124/es-demo

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yh_124

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值