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);
        }
    }
相关推荐
方圆想当图灵16 分钟前
缓存之美:万文详解 Caffeine 实现原理(下)
java·redis·缓存
喝醉酒的小白28 分钟前
Elasticsearch 中,分片(Shards)数量上限?副本的数量?
大数据·elasticsearch·jenkins
栗豆包30 分钟前
w175基于springboot的图书管理系统的设计与实现
java·spring boot·后端·spring·tomcat
等一场春雨1 小时前
Java设计模式 十四 行为型模式 (Behavioral Patterns)
java·开发语言·设计模式
萧若岚1 小时前
Elixir语言的Web开发
开发语言·后端·golang
Channing Lewis2 小时前
flask实现重启后需要重新输入用户名而避免浏览器使用之前已经记录的用户名
后端·python·flask
Channing Lewis2 小时前
如何在 Flask 中实现用户认证?
后端·python·flask
酱学编程2 小时前
java中的单元测试的使用以及原理
java·单元测试·log4j
我的运维人生2 小时前
Java并发编程深度解析:从理论到实践
java·开发语言·python·运维开发·技术共享
一只爱吃“兔子”的“胡萝卜”2 小时前
2.Spring-AOP
java·后端·spring