本篇文章建立在对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());
}
}
}
使用滚动搜索的优点是可以处理大量数据,而无需一次性将所有结果加载到内存中。通过逐步获取数据,可以避免内存溢出的问题,并提高搜索的效率。
感谢阅读!