Springboot集成ES详解
找官方文档
官方文档地址:https://www.elastic.co/guide/index.html
- 找到原生的依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.8.0</version>
</dependency>
- 找相关的对象(初始化)
- 分析这个类中的方法即可
配置基本的项目
问题:一定要保证我们导入的依赖和我们ES的版本一致
源码中提供对象
虽然这里导入了三个静态内部类,核心类就一个
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.boot.autoconfigure.elasticsearch;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.Duration;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
class ElasticsearchRestClientConfigurations {
ElasticsearchRestClientConfigurations() {
}
private static class PropertiesCredentialsProvider extends BasicCredentialsProvider {
PropertiesCredentialsProvider(ElasticsearchRestClientProperties properties) {
if (StringUtils.hasText(properties.getUsername())) {
Credentials credentials = new UsernamePasswordCredentials(properties.getUsername(), properties.getPassword());
this.setCredentials(AuthScope.ANY, credentials);
}
properties.getUris().stream().map(this::toUri).filter(this::hasUserInfo).forEach(this::addUserInfoCredentials);
}
private URI toUri(String uri) {
try {
return URI.create(uri);
} catch (IllegalArgumentException var3) {
return null;
}
}
private boolean hasUserInfo(URI uri) {
return uri != null && StringUtils.hasLength(uri.getUserInfo());
}
private void addUserInfoCredentials(URI uri) {
AuthScope authScope = new AuthScope(uri.getHost(), uri.getPort());
Credentials credentials = this.createUserInfoCredentials(uri.getUserInfo());
this.setCredentials(authScope, credentials);
}
private Credentials createUserInfoCredentials(String userInfo) {
int delimiter = userInfo.indexOf(":");
if (delimiter == -1) {
return new UsernamePasswordCredentials(userInfo, (String)null);
} else {
String username = userInfo.substring(0, delimiter);
String password = userInfo.substring(delimiter + 1);
return new UsernamePasswordCredentials(username, password);
}
}
}
static class DefaultRestClientBuilderCustomizer implements RestClientBuilderCustomizer {
private static final PropertyMapper map = PropertyMapper.get();
private final ElasticsearchRestClientProperties properties;
DefaultRestClientBuilderCustomizer(ElasticsearchRestClientProperties properties) {
this.properties = properties;
}
public void customize(RestClientBuilder builder) {
}
public void customize(HttpAsyncClientBuilder builder) {
builder.setDefaultCredentialsProvider(new ElasticsearchRestClientConfigurations.PropertiesCredentialsProvider(this.properties));
}
public void customize(Builder builder) {
PropertyMapper var10000 = map;
ElasticsearchRestClientProperties var10001 = this.properties;
var10001.getClass();
var10000.from(var10001::getConnectionTimeout).whenNonNull().asInt(Duration::toMillis).to(builder::setConnectTimeout);
var10000 = map;
var10001 = this.properties;
var10001.getClass();
var10000.from(var10001::getReadTimeout).whenNonNull().asInt(Duration::toMillis).to(builder::setSocketTimeout);
}
}
@Configuration(
proxyBeanMethods = false
)
static class RestClientFallbackConfiguration {
RestClientFallbackConfiguration() {
}
//RestClient 普通的客户端
@Bean
@ConditionalOnMissingBean
RestClient elasticsearchRestClient(RestClientBuilder builder) {
return builder.build();
}
}
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({RestHighLevelClient.class})
static class RestHighLevelClientConfiguration {
RestHighLevelClientConfiguration() {
}
//RestHighLevelClient 高级客户端,后面项目会用到的客户端
@Bean
@ConditionalOnMissingBean
RestHighLevelClient elasticsearchRestHighLevelClient(RestClientBuilder restClientBuilder) {
return new RestHighLevelClient(restClientBuilder);
}
//RestClientBuilder
@Bean
@ConditionalOnMissingBean
RestClient elasticsearchRestClient(RestClientBuilder builder, ObjectProvider<RestHighLevelClient> restHighLevelClient) {
RestHighLevelClient client = (RestHighLevelClient)restHighLevelClient.getIfUnique();
return client != null ? client.getLowLevelClient() : builder.build();
}
}
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnMissingBean({RestClientBuilder.class})
static class RestClientBuilderConfiguration {
RestClientBuilderConfiguration() {
}
@Bean
RestClientBuilderCustomizer defaultRestClientBuilderCustomizer(ElasticsearchRestClientProperties properties) {
return new ElasticsearchRestClientConfigurations.DefaultRestClientBuilderCustomizer(properties);
}
@Bean
RestClientBuilder elasticsearchRestClientBuilder(ElasticsearchRestClientProperties properties, ObjectProvider<RestClientBuilderCustomizer> builderCustomizers) {
HttpHost[] hosts = (HttpHost[])properties.getUris().stream().map(this::createHttpHost).toArray((x$0) -> {
return new HttpHost[x$0];
});
RestClientBuilder builder = RestClient.builder(hosts);
builder.setHttpClientConfigCallback((httpClientBuilder) -> {
builderCustomizers.orderedStream().forEach((customizer) -> {
customizer.customize(httpClientBuilder);
});
return httpClientBuilder;
});
builder.setRequestConfigCallback((requestConfigBuilder) -> {
builderCustomizers.orderedStream().forEach((customizer) -> {
customizer.customize(requestConfigBuilder);
});
return requestConfigBuilder;
});
builderCustomizers.orderedStream().forEach((customizer) -> {
customizer.customize(builder);
});
return builder;
}
private HttpHost createHttpHost(String uri) {
try {
return this.createHttpHost(URI.create(uri));
} catch (IllegalArgumentException var3) {
return HttpHost.create(uri);
}
}
private HttpHost createHttpHost(URI uri) {
if (!StringUtils.hasLength(uri.getUserInfo())) {
return HttpHost.create(uri.toString());
} else {
try {
return HttpHost.create((new URI(uri.getScheme(), (String)null, uri.getHost(), uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment())).toString());
} catch (URISyntaxException var3) {
throw new IllegalStateException(var3);
}
}
}
}
}
配置bean
package com.czu.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Spring两步骤:
* 1. 找到对象
* 2. 放到Spring中待用
* 3. 如果是SpringBoot就先分析源码
*
* @author 87682
*/
@Configuration
public class ElasticSearchClientConfig {
@Bean
public RestHighLevelClient restHighLevelClient() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("127.0.0.1", 9200, "http")));
return client;
}
}
具体的API测试
- 创建索引
- 判断索引是否存在
- 删除索引
- 创建文档
- CRUD文档
package com.czu;
import com.alibaba.fastjson.JSON;
import com.czu.pojo.User;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
/**
* 讲解ES 7.8.0 高级客户端API测试
*/
@SpringBootTest
class SpringbootEsApiApplicationTests {
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
/**
* 测试索引的创建 Request
*/
@Test
void testCreateIndex() throws IOException {
//1. 创建索引请求
CreateIndexRequest request = new CreateIndexRequest("hzy_index");
//2. 客户端执行创建请求 自动补全返回值快捷键(ctrl+alt+v)
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(createIndexResponse);
}
/**
* 测试获取索引,判断其是否存在
*/
@Test
void testExistIndex() throws IOException {
GetIndexRequest request = new GetIndexRequest("hzy_index");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}
/**
* 测试删除索引
*/
@Test
void testDeleteIndex() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("hzy_index");
AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
System.out.println(delete.isAcknowledged());
}
/**
* 测试添加文档
*/
@Test
void testAddDocument() throws IOException {
//创建对象
User user = new User("流云飘雨", 3);
//创建请求
IndexRequest request = new IndexRequest("hzy_index");
//规则 PUT /hzy_index/_doc/1
request.id("1");
request.timeout(TimeValue.timeValueSeconds(1));
//request.timeout("1s");
//将我们的数据放入请求 json
request.source(JSON.toJSONString(user), XContentType.JSON);
//客户端发送请求
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
//返回创建文档的JSON字符串信息
System.out.println(indexResponse.toString());
//对应我们命令返回的状态
System.out.println(indexResponse.status());
}
/**
* 获取文档,判断是否存在 GET /hzy_index/_doc/1
*/
@Test
void testIsExists() throws IOException {
GetRequest getRequest = new GetRequest("hzy_index", "1");
//不获取返回的_source的上下文了
getRequest.fetchSourceContext(new FetchSourceContext(false));
getRequest.storedFields("_none_");
boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
System.out.println(exists);
}
/**
* 获取文档的信息
*/
@Test
void testGetDocument() throws IOException {
GetRequest getRequest = new GetRequest("hzy_index", "1");
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
//打印文档的内容
System.out.println(getResponse.getSourceAsString());
//返回的全部内容和命令是一样的
System.out.println(getResponse);
}
/**
* 更新文档的信息
*/
@Test
void testUpdateDocument() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("hzy_index", "1");
updateRequest.timeout("1s");
User user = new User("流云飘雨233", 18);
updateRequest.doc(JSON.toJSONString(user), XContentType.JSON);
UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
System.out.println(updateResponse.status());
}
/**
* 删除文档记录
*/
@Test
void testDeleteDocument() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest("hzy_index", "1");
deleteRequest.timeout("1s");
DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(deleteResponse.status());
}
/**
* 特殊的,真实的项目一般都会批量插入数据
*/
@Test
void testBulkRequest() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("10s");
ArrayList<User> userList = new ArrayList<>();
userList.add(new User("hzy1", 3));
userList.add(new User("hzy2", 3));
userList.add(new User("hzy3", 3));
//批处理请求
for (int i = 0; i < userList.size(); i++) {
//批量更新和批量删除,就在这里修改对应的请求就可以了
bulkRequest.add(
new IndexRequest("hzy_index")
.id("" + (i + 1))
.source(JSON.toJSONString(userList.get(i)), XContentType.JSON)
);
}
BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
//是否失败,成功返回false,失败返回true
System.out.println(bulkResponse.hasFailures());
}
/**
* 查询
* SearchRequest 搜索请求
* SearchSourceBuilder 条件构造
* HighLightBuilder 构建高亮
* MatchAllQueryBuilder 匹配所有
* TermQueryBuilder 精确查询
* xxxQueryBuilder 对应我们刚才看到的命令
*/
@Test
void testSearchRequest() throws IOException {
SearchRequest searchRequest = new SearchRequest("hzy_index");
//构建搜索的条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//查询条件,我们可以使用QueryBuilders工具类来实现
//QueryBuilders.termQuery() 精确查询
//QueryBuilders.matchAllQuery() 匹配所有
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "hzy1");
searchSourceBuilder.query(termQueryBuilder);
searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
//注意这里fastjson版本要用最新版本,不然转换JSON的时候会出现版本冲突
System.out.println(JSON.toJSONString(searchResponse.getHits()));
System.out.println("==============================");
for (SearchHit documentFields : searchResponse.getHits().getHits()) {
System.out.println(documentFields.getSourceAsMap());
}
}
}