springboot通过客户端访问elasticsearch数据

本篇文章建立在对springboot会使用的基础上,想要连接elasticsearch并获取数据

一、引入java连接es依赖

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>${elasticsearch.version}</version>
</dependency>

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>${elasticsearch.version}</version>
</dependency>

二、创建RestHighLevelClient注入Spring容器

        这一步以配置类的方式将RestHighLevelClient实例注入Spring容器,为后续可以直接通过@Autowired做准备

2.1、配置application.yaml

在application.yaml自定义写上es所在节点的ip以及端口,为后续使用

elasticsearch:
  ip: es所在节点:9200

2.2、配置EsConfig

配置spring配置类:

名为EsConfig。它用于配置与Elasticsearch的连接。

在这个类中,有以下关键部分:

1、静态变量ADDRESS_LENGTH和HTTP_SCHEME:这些变量用于定义Elasticsearch的地址格式和协议。

2、实例变量ipAddress:通过@Value注解从配置文件中获取Elasticsearch的IP地址,并将其存储在一个字符串数组中。

3、restHighLevelClient方法:这是一个@Bean方法,用于创建并返回一个RestHighLevelClient实例,该实例用于与Elasticsearch进行高级别的REST通信。它接受一个RestClientBuilder实例作为参数,通过@Autowired注解进行自动注入。

4、restClientBuilder方法:这是另一个@Bean方法,用于创建并返回一个RestClientBuilder实例,该实例用于构建与Elasticsearch的低级别REST通信。它根据ipAddress数组中的IP地址创建一个HttpHost数组,并将其传递给RestClient.builder方法。过滤掉无效的地址后,通过流操作(map、filter)进行转换和过滤,并使用toArray方法将其转换为HttpHost数组。

5、makeHttpHost方法:这是一个私有方法,用于将IP地址字符串拆分为IP和端口,并创建一个HttpHost实例。它通过解析address数组的长度来检查地址格式是否正确,并返回相应的HttpHost实例。如果地址格式不正确,将返回null。

这个类的作用是根据配置文件中的Elasticsearch IP地址创建与Elasticsearch的连接,然后使用RestHighLevelClient进行高级别的REST通信。

@Configuration
public class EsConfig {

    private static final int ADDRESS_LENGTH = 2;
    private static final String HTTP_SCHEME = "http";

    @Value("${elasticsearch.ip}")
    String[] ipAddress;

    @Bean
    public RestHighLevelClient restHighLevelClient(@Autowired RestClientBuilder restClientBuilder){
        return new RestHighLevelClient(restClientBuilder);
    }

    @Bean
    public RestClientBuilder restClientBuilder(){
        HttpHost[] hosts = Arrays.stream(ipAddress)
                .map(this::makeHttpHost)
                .filter(Objects::nonNull)
                .toArray(HttpHost[]::new);

        return RestClient.builder(hosts);
    }

    private HttpHost makeHttpHost(String s){
        String[] address = s.split(":");
        if (address.length == ADDRESS_LENGTH){
            String ip = address[0];
            int port = Integer.parseInt(address[1]);
            return new HttpHost(ip, port, HTTP_SCHEME);
        }else {
            return null;
        }
    }

}

通过这种方式,在其他的类中,我们可以通过注入RestHighLevelClient进行使用

    @Autowired
    private RestHighLevelClient restHighLevelClient;

三、查询Es数据

3.1、类和API知识点讲解

1、滚动搜索(Scroll API):如果不使用滚轮搜索,es默认只会返回1000条数据。滚动搜索是一种用于在Elasticsearch中获取大批量数据的机制。通常情况下,一次搜索请求只返回一定数量的结果,如果需要获取更多结果,需要使用滚动搜索来进行连续的滚动查询。滚动搜索的原理是通过首次搜索请求获取滚动ID,然后使用该滚动ID发送后续的滚动请求,以获取更多的搜索结果。


使用滚动搜索获取数据的原理:通过初始的搜索请求,获取一批搜索结果及滚动ID。然后,使用该滚动ID发送后续的滚动请求,每次获取一批结果,直到结果为空。在每次滚动请求中,都会包含滚动ID和滚动时间间隔,用于告知Elasticsearch要获取哪批数据以及下一次滚动操作的时间间隔。这样,通过多次滚动请求,就可以逐步获取全部数据。

2、SearchRequest:SearchRequest是Elasticsearch Java High-Level REST Client中的一个类,用于配置搜索请求的参数,如索引名称、查询条件、排序方式等。

3、SearchSourceBuilder:SearchSourceBuilder是一个构建搜索请求的工具类,可以设置搜索的各种参数,如查询条件、聚合操作、排序方式等。

4、BoolQueryBuilder:BoolQueryBuilder是一个用于构建布尔查询的工具类,可以组合多个查询条件,并指定它们之间的关系,如must表示必须满足所有条件,should表示至少满足一个条件,mustNot表示不能满足某个条件等。

5、scroll方法:scroll方法用于设置滚动搜索的时间间隔。它接受一个TimeValue参数,表示时间间隔的单位,可以是毫秒、秒、分钟等。

在代码中,首先创建了一个初始的搜索请求,并通过scroll方法设置了滚动时间间隔。然后,通过SearchResponse获取滚动ID和搜索结果。接下来,使用滚动ID循环发送滚动请求,每次获取一批结果,这批数据可以将每条数据以字符串方式获取出来 你可以通过JSON转化工具将字符串转化为vo类 ,直到搜索结果为空。最后,通过ClearScrollRequest清除滚动上下文。

3.2、完整代码

使用Spring的单元测试

相应依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <version>${springboot.version}</version>
</dependency>
import org.elasticsearch.action.search.*;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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


/**
 * @author Csir
 */
@SpringBootTest
public class GetEsData {
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Test
    public void test(){
        TimeValue scrollTime = TimeValue.timeValueMillis(1);

        // TODO 选择索引名
        SearchRequest request = new SearchRequest("索引名");
        request.scroll(scrollTime);

        // 创建SearchSourceBuilder对象,用于构建搜索请求的查询条件和其他设置
        SearchSourceBuilder builder = new SearchSourceBuilder();
        // 设置trackTotalHits参数为true,以获取匹配查询条件的所有文档总数
        builder.trackTotalHits(true);

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        builder.query(boolQueryBuilder);

        // TODO 对布尔查询builder进行配置  自行选择模糊查询需要must还是should(相当于or)的关系
        List<QueryBuilder> must = boolQueryBuilder.must();
        // List<QueryBuilder> should = boolQueryBuilder.should();

        request.source(builder);

        // TODO 选择查询条件
        // 精准查询
        must.add(QueryBuilders.matchQuery("字段名", "匹配值"));
        // 范围查询
        must.add(QueryBuilders.rangeQuery("字段名").lte("小于").gte("大于"));

        try {
            SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            String scrollId = searchResponse.getScrollId();
            SearchHits searchHits = searchResponse.getHits();
            // 检查是否还有命中的搜索结果
            while (searchHits.getHits().length != 0) {
                for (SearchHit hit : searchHits.getHits()) {
                    // TODO 获取到了一条数据的字符串,可以通过JSON转化为vo类。。。
                    String source = hit.getSourceAsString();
                }
                // 创建滚动请求,使用上一次的 scrollId
                SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
                scrollRequest.scroll(scrollTime);
                searchResponse = restHighLevelClient.scroll(scrollRequest, RequestOptions.DEFAULT);
                scrollId = searchResponse.getScrollId();
                searchHits = searchResponse.getHits();
            }

            // 清除滚动上下文
            ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
            clearScrollRequest.addScrollId(scrollId);

            ClearScrollResponse clearScrollResponse = restHighLevelClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);

            boolean succeeded = clearScrollResponse.isSucceeded();
            if (!succeeded) {
                System.err.println("Failed to clear scroll context.");
            }
        } catch (IOException e) {
            System.err.println("Error during Elasticsearch search: " + e.getMessage());
        }
    }
}

使用滚动搜索的优点是可以处理大量数据,而无需一次性将所有结果加载到内存中。通过逐步获取数据,可以避免内存溢出的问题,并提高搜索的效率。

感谢阅读!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值