Elasticsearch8.8.0 SpringBoot实战操作各种案例(索引操作、聚合、复杂查询、嵌套等)

Elasticsearch8.8.0 全网最新版教程 从入门到精通 通俗易懂

配置项目

引入依赖

复制代码
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.16</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>co.elastic.clients</groupId>
            <artifactId>elasticsearch-java</artifactId>
            <version>8.8.0</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.3</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.3</version>
        </dependency>
        <dependency>
            <groupId>jakarta.json</groupId>
            <artifactId>jakarta.json-api</artifactId>
            <version>2.0.1</version>
        </dependency>

添加配置文件

application.yaml

复制代码
spring:
  elasticsearch:
    rest:
      scheme: https
      host: localhost
      port: 9200
      username: elastic
      password: 123456
      crt: classpath:ca.crt

导入ca证书到项目中

从任意一个es容器中,拷贝证书到resources目录下

复制代码
/usr/share/elasticsearch/config/certs/ca

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EXytUrDp-1691330960034)(media/16912196423122/16912204609393.jpg)

添加配置

复制代码
package com.lglbc.elasticsearch;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.TransportUtils;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader;

import javax.net.ssl.SSLContext;
import java.io.IOException;

/**
 * @Description TODO
 * @Author 关注公众号 "乐哥聊编程" 领取资料和源码 
 * @Date 2023/07/14 21:04
 */
@Configuration
public class ElasticConfig {
    @Value("${spring.elasticsearch.rest.scheme}")
    private String scheme;
    @Value("${spring.elasticsearch.rest.host}")
    private String host;
    @Value("${spring.elasticsearch.rest.port}")
    private int port;
    @Value("${spring.elasticsearch.rest.crt}")
    private String crt;
    @Value("${spring.elasticsearch.rest.username}")
    private String username;
    @Value("${spring.elasticsearch.rest.password}")
    private String password;
    @Autowired
    private ResourceLoader resourceLoader;

    @Bean
    public ElasticsearchClient elasticsearchClient() throws IOException {

        SSLContext sslContext = TransportUtils
                .sslContextFromHttpCaCrt(resourceLoader.getResource(crt).getFile());
        BasicCredentialsProvider credsProv = new BasicCredentialsProvider();
        credsProv.setCredentials(
                AuthScope.ANY, new UsernamePasswordCredentials(username, password)
        );

        RestClient restClient = RestClient
                .builder(new HttpHost(host, port, scheme))
                .setHttpClientConfigCallback(hc -> hc
                        .setSSLContext(sslContext)
                        .setDefaultCredentialsProvider(credsProv)
                )
                .build();

// Create the transport and the API client
        ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
        ElasticsearchClient client = new ElasticsearchClient(transport);
        return client;
    }
}

实战操作

创建mapping

复制代码
    @Test
    public void testCreateMapping() throws IOException {
        PutMappingRequest mappingRequest = new PutMappingRequest.Builder().index("lglbc_java_demo")
                .properties("order_no", builder ->
                        builder.keyword(type -> type)
                ).properties("order_time", builder ->
                        builder.date(type -> type.format("yyyy-MM-dd HH:mm:ss"))
                ).properties("good_info", type -> type.nested(
                        nested -> nested
                                .properties("good_price", builder ->
                                        builder.double_(subType -> subType))
                                .properties("good_count", builder ->
                                        builder.integer(subType -> subType))
                                .properties("good_name", builder ->
                                        builder.text(subType ->
                                                subType.fields("keyword", subTypeField -> subTypeField.keyword(subSubType -> subSubType)))
                                ))
                ).properties("buyer", builder ->
                        builder.keyword(type -> type)
                ).properties("phone", builder ->
                        builder.keyword(type -> type)
                )
                .build();
        ElasticsearchIndicesClient indices = elasticsearchClient.indices();
        if (indices.exists(request -> request.index("lglbc_java_demo")).value()) {
            indices.delete(request -> request.index("lglbc_java_demo"));
        }
        indices.create(request -> request.index("lglbc_java_demo"));
        indices.putMapping(mappingRequest);
    }

创建文档

复制代码
@Test
    public void testAddData() throws IOException {
        OrderInfo orderInfo = new OrderInfo("1001", new Date(), "李白", "13098762567");
        List<OrderInfo.GoodInfo> goodInfos = new ArrayList<>();
        goodInfos.add(new OrderInfo.GoodInfo("苹果笔记本", 30.5d, 30));
        goodInfos.add(new OrderInfo.GoodInfo("苹果手机", 20.5d, 10));
        orderInfo.setGoodInfo(goodInfos);
        IndexRequest<OrderInfo> request = IndexRequest.of(i -> i
                .index("lglbc_java_demo")
                .id(orderInfo.getOrderNo())
                .document(orderInfo)
        );
        OrderInfo orderInfo2 = new OrderInfo("1002", new Date(), "苏轼", "13098762367");
        List<OrderInfo.GoodInfo> goodInfos2 = new ArrayList<>();
        goodInfos2.add(new OrderInfo.GoodInfo("华为笔记本", 18.5d, 15));
        goodInfos2.add(new OrderInfo.GoodInfo("苹果手机", 20.5d, 10));
        orderInfo2.setGoodInfo(goodInfos2);
        IndexRequest<OrderInfo> request2 = IndexRequest.of(i -> i
                .index("lglbc_java_demo")
                .id(orderInfo2.getOrderNo())
                .document(orderInfo2)
        );
        elasticsearchClient.index(request);
        elasticsearchClient.index(request2);
    }

查询更新

复制代码
    @Test
    public void testUpdateDataByQuery() throws IOException {
        UpdateByQueryRequest request = UpdateByQueryRequest.of(i -> i
                .index("lglbc_java_demo")
                .query(query -> query.term(term -> term.field("order_no").value("1001")))
                .script(script -> script.inline(inline -> inline.lang("painless").source("ctx._source['buyer'] = 'java 更新->乐哥聊编程'")))
        );
        elasticsearchClient.updateByQuery(request);
    }

全量更新

复制代码
    @Test
    public void testUpdateData() throws IOException {
        OrderInfo orderInfo3 = new OrderInfo("1002", new Date(), "苏轼3", "13098762367");
        List<OrderInfo.GoodInfo> goodInfos3 = new ArrayList<>();
        goodInfos3.add(new OrderInfo.GoodInfo("华为笔记本", 18.5d, 15));
        goodInfos3.add(new OrderInfo.GoodInfo("苹果手机", 20.5d, 10));
        orderInfo3.setGoodInfo(goodInfos3);
        UpdateRequest request = UpdateRequest.of(i -> i
                .index("lglbc_java_demo")
                .id(orderInfo3.getOrderNo())
                .doc(orderInfo3)
        );
        elasticsearchClient.update(request, OrderInfo.class);
    }

删除数据

复制代码
    @Test
    public void testDelete() throws IOException {
        DeleteRequest request = DeleteRequest.of(i -> i
                .index("lglbc_java_demo")
                .id("1002")
        );
        elasticsearchClient.delete(request);
    }

批量操作(bulk)

复制代码
    @Test
    public void testBulkOperation() throws IOException {
        testCreateMapping();
        BulkRequest.Builder br = new BulkRequest.Builder();
        List<OrderInfo> orders = getOrders();
        for (OrderInfo orderInfo : orders) {
            br.operations(op -> op
                    .index(idx -> idx
                            .index("lglbc_java_demo")
                            .document(orderInfo)
                    )
            );
        }
        elasticsearchClient.bulk(br.build());
    }

基本搜索

复制代码
    @Test
    public void testBaseSearch() throws IOException {
        SearchRequest request = SearchRequest.of(i -> i
                .index("lglbc_java_demo")
                .query(query -> query.term(
                        term -> term.field("order_no").value("1001")
                )));
        SearchResponse<OrderInfo> response = elasticsearchClient.search(request, OrderInfo.class);
        List<Hit<OrderInfo>> hits = response.hits().hits();
        List<OrderInfo> orderInfos = new ArrayList<>();
        for (Hit hit : hits) {
            orderInfos.add((OrderInfo) hit.source());
        }
        System.out.println(JSONUtil.toJsonStr(orderInfos));
    }

复杂布尔搜索

复制代码
    @Test
    public void testBoolSearch() throws IOException {
        SearchRequest request = SearchRequest.of(i -> i
                .index("lglbc_java_demo")
                .query(query -> query.bool(bool -> bool
                        .filter(filterQuery -> filterQuery.term(term -> term.field("buyer").value("李白")))
                        .must(must -> must.term(term -> term.field("order_no").value("1004"))))));
        SearchResponse<OrderInfo> response = elasticsearchClient.search(request, OrderInfo.class);
        List<Hit<OrderInfo>> hits = response.hits().hits();
        List<OrderInfo> orderInfos = new ArrayList<>();
        for (Hit hit : hits) {
            orderInfos.add((OrderInfo) hit.source());
        }
        System.out.println(JSONUtil.toJsonStr(orderInfos));
    }

嵌套(nested)搜索

复制代码
    @Test
    public void testNestedSearch() throws IOException {
        SearchRequest request = SearchRequest.of(i -> i
                .index("lglbc_java_demo")
                .query(query -> query.nested(nested -> nested
                        .path("good_info")
                        .query(nestedQuery -> nestedQuery.bool(
                                        bool -> bool
                                                .must(must -> must.range(range -> range.field("good_info.good_count").gte(JsonData.of("16"))))
                                                .must(must2 -> must2.range(range -> range.field("good_info.good_price").gte(JsonData.of("30"))))
                                )
                        )
                )));
        SearchResponse<OrderInfo> response = elasticsearchClient.search(request, OrderInfo.class);
        List<Hit<OrderInfo>> hits = response.hits().hits();
        List<OrderInfo> orderInfos = new ArrayList<>();
        for (Hit hit : hits) {
            orderInfos.add((OrderInfo) hit.source());
        }
        System.out.println(JSONUtil.toJsonStr(orderInfos));
    }

分页查询

复制代码
   @Test
    public void testBasePageSearch() throws IOException {
        SearchRequest request = SearchRequest.of(i -> i
                .index("lglbc_java_demo")
                .from(0)
                .size(2).query(query -> query.matchAll(matchAll -> matchAll)));
        SearchResponse<OrderInfo> response = elasticsearchClient.search(request, OrderInfo.class);
        List<Hit<OrderInfo>> hits = response.hits().hits();
        List<OrderInfo> orderInfos = new ArrayList<>();
        for (Hit hit : hits) {
            orderInfos.add((OrderInfo) hit.source());
        }
        System.out.println(orderInfos.size());

        request = SearchRequest.of(i -> i
                .index("lglbc_java_demo")
                .from(2)
                .size(2).query(query -> query.matchAll(matchAll -> matchAll)));
        response = elasticsearchClient.search(request, OrderInfo.class);
        hits = response.hits().hits();
        orderInfos = new ArrayList<>();
        for (Hit hit : hits) {
            orderInfos.add((OrderInfo) hit.source());
        }
        System.out.println(orderInfos.size());

        request = SearchRequest.of(i -> i
                .index("lglbc_java_demo")
                .from(4)
                .size(2).query(query -> query.matchAll(matchAll -> matchAll)));
        response = elasticsearchClient.search(request, OrderInfo.class);
        hits = response.hits().hits();
        orderInfos = new ArrayList<>();
        for (Hit hit : hits) {
            orderInfos.add((OrderInfo) hit.source());
        }
        System.out.println(orderInfos.size());
    }

滚动分页查询

复制代码
@Test
    public void testScrollPageSearch() throws IOException {
        String scrollId = null;
        while (true) {
            List<OrderInfo> orderInfos = new ArrayList<>();
            if (StringUtils.isBlank(scrollId)) {
                SearchRequest request = SearchRequest.of(i -> i
                        .index("lglbc_java_demo")
                        .scroll(Time.of(time -> time.time("1m")))
                        .size(2)
                        .query(query -> query.matchAll(matchAll -> matchAll)));
                SearchResponse<OrderInfo> response = elasticsearchClient.search(request, OrderInfo.class);
                List<Hit<OrderInfo>> hits = response.hits().hits();
                for (Hit hit : hits) {
                    orderInfos.add((OrderInfo) hit.source());
                }
                scrollId = response.scrollId();
            } else {
                String finalScrollId = scrollId;
                ScrollRequest request = ScrollRequest.of(i -> i
                        .scroll(Time.of(time -> time.time("1m")))
                        .scrollId(finalScrollId));
                ScrollResponse response = elasticsearchClient.scroll(request, OrderInfo.class);
                List<Hit<OrderInfo>> hits = response.hits().hits();
                for (Hit hit : hits) {
                    orderInfos.add((OrderInfo) hit.source());
                }
                scrollId = response.scrollId();
            }
            if (CollectionUtil.isEmpty(orderInfos)) {
                break;
            }
            System.out.println(orderInfos.size());
        }
    }

After分页查询

复制代码
@Test
    public void testAfterPageSearch() throws IOException {
        final List<FieldValue>[] sortValue = new List[]{new ArrayList<>()};
        while (true) {
            List<OrderInfo> orderInfos = new ArrayList<>();
            SearchRequest request = SearchRequest.of(i -> {
                SearchRequest.Builder sort1 = i
                        .index("lglbc_java_demo")
                        .size(2)
                        .sort(Lists.list(
                                SortOptions.of(sort -> sort.field(field -> field.field("order_no").order(SortOrder.Desc))))
                        );
                if (CollectionUtil.isNotEmpty(sortValue[0])) {
                    sort1.searchAfter(sortValue[0]);
                }
                return sort1
                        .query(query -> query.matchAll(matchAll -> matchAll));
            });
            SearchResponse<OrderInfo> response = elasticsearchClient.search(request, OrderInfo.class);
            List<Hit<OrderInfo>> hits = response.hits().hits();
            for (Hit hit : hits) {
                orderInfos.add((OrderInfo) hit.source());
                sortValue[0] = hit.sort();
            }
            if (CollectionUtil.isEmpty(orderInfos)) {
                break;
            }
            System.out.println(orderInfos.size());
        }

    }

词条(terms)聚合

复制代码
@Test
    public void testTermsAgg() throws IOException {
        SearchRequest request = SearchRequest.of(i -> i
                .index("lglbc_java_demo")
                .query(query -> query
                        .matchAll(match->match))
                .aggregations("agg_term_buyer",agg->agg
                        .dateHistogram(dateHistogram->dateHistogram
                                .field("order_time")
                                .calendarInterval(CalendarInterval.Day))));
        SearchResponse<Void> search = elasticsearchClient.search(request, Void.class);
        Map<String, Aggregate> aggregations = search.aggregations();
        Aggregate aggregate = aggregations.get("agg_term_buyer")
                ;
        Buckets<StringTermsBucket> buckets = ((StringTermsAggregate) aggregate._get()).buckets();
        for (StringTermsBucket bucket : buckets.array()) {
            String key = bucket.key()._toJsonString();
            long l = bucket.docCount();
            System.out.println(key+":::"+l);
        }
    }

日期聚合

复制代码
@Test
    public void testDateAgg() throws IOException {
        SearchRequest request = SearchRequest.of(i -> i
                .index("lglbc_java_demo")
                .query(query -> query
                        .matchAll(match->match))
                .aggregations("agg_date_buyer",agg->agg
                        .dateHistogram(dateHistogram->dateHistogram
                                .field("order_time")
                                .calendarInterval(CalendarInterval.Day))));
        SearchResponse<Void> search = elasticsearchClient.search(request, Void.class);
        Map<String, Aggregate> aggregations = search.aggregations();
        Aggregate aggregate = aggregations.get("agg_date_buyer");
        List<DateHistogramBucket> buckets = ((DateHistogramAggregate) aggregate._get()).buckets().array();
        System.out.println(aggregate);
        for (DateHistogramBucket bucket : buckets) {
            String key = bucket.keyAsString();
            long l = bucket.docCount();
            System.out.println(key+":::"+l);
        }
    }
相关推荐
wadesir7 分钟前
深入理解Rust静态生命周期(从零开始掌握‘static的奥秘)
开发语言·后端·rust
+VX:Fegn089512 分钟前
计算机毕业设计|基于springboot + vue零食商城管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
哈哈哈笑什么20 分钟前
蜜雪冰城1分钱奶茶秒杀活动下,使用分片锁替代分布式锁去做秒杀系统
redis·分布式·后端
Query*28 分钟前
杭州2024.08 Java开发岗面试题分类整理【附面试技巧】
java·开发语言·面试
WZTTMoon35 分钟前
Spring Boot 4.0 迁移核心注意点总结
java·spring boot·后端
寻kiki36 分钟前
scala 函数类?
后端
疯狂的程序猴1 小时前
iOS App 混淆的真实世界指南,从构建到成品 IPA 的安全链路重塑
后端
旷野说1 小时前
为什么 MyBatis 原生二级缓存“难以修复”?
java·java-ee·mybatis
8***23551 小时前
【wiki知识库】07.用户管理后端SpringBoot部分
java
bcbnb1 小时前
iOS 性能测试的工程化方法,构建从底层诊断到真机监控的多工具测试体系
后端