RestHighLevelClient 用法示例(创建、删除、查询索引库;添加、查询、删除文档)
1、启动 Elasticsearch 服务器:
打开命令行窗口(小黑窗),输入命令: elasticsearch ,即可启动 Elasticsearch 服务器
2、因为去掉SSL证书验证,所以向Elasticsearch服务器发送请求的时候,是使用 http 协议。
Spring Boot 只要检测到类路径下有 elasticsearch-rest-high-level-client 依赖(无需Spring Data Elasticsearch),Spring Boot 就会在容器中创建一个自动配置的 RestHighLevelClient,它就是Elasticsearch 的高级 RestClient 客户端。
当容器中有了这个自动配置的 RestHighLevelClient (高级RestClient)之后,我们(或者说容器)就可以将它注入到其他任何组件(主要是DAO组件),通过它来操作 Elasticsearch 索引库。
测试类——代码演示:
去掉 SSL 证书验证
让项目通过 HTTPS 连接 Elasticsearch 的配置
把这个存放公钥证书的密钥库删掉
配置文件不启动SSL 证书验证
配置文件里面,用 http 连接就可以了,不需要用 https 连接。
ElasticsearchConfig 类里面的一些定制也注释掉
重启 Elasticsearch 服务器。
就是打开小黑窗,也就是命令行窗口,输入:elasticsearch 即可启动服务器。
1、创建 index 索引库
我原先使用的Elasticsearch的依赖版本是7.14.1,但是测试的时候报错,提示elasticsearchRestHighLevelClient这个bean创建失败,所以 修改依赖版本为7.12.0 就好了
代码
测试结果
通过 postman 发送 http://localhost:9200/_cat/indices 查询所有索引库,可以看到创建索引库成功
查看指定索引库:http://localhost:9200/books/
2、删除 index 索引库
代码
测试结果
如图,刚刚添加的三个索引库,只剩下 books 这个索引库了
删除索引库成功
3、查询所有 index 索引库
代码和结果
成功查询出Elasticsearch服务器里面的所有索引库
4、往索引库里面添加文档
代码演示:
测试结果
查询指定索引库的所有文档:http://localhost:9200/books/_search
_search 的作用就是查看该索引库的所有文档
如图:往索引库添加文档成功
如果查询条件不加 _search,则只是查询该索引库的配置
如图:http://localhost:9200/books 不加 _search,查出来是索引库的基本数据配置之类的。
5、根据索引库内文档的id查询文档
代码和结果
如图:根据文档的id查询文档成功。
6、根据条件查询文档(通配符和关键字)
代码
测试结果
普通关键字查询和通配符查询都能正确查询出来
7、根据 id 删除文档
代码
测试结果
查询 books 索引库的全部文档:http://localhost:9200/books/_search
可以看到id 为 3 和 4 的文档已经被成功删除了。
具体代码
ElasticsearchConfig 配置类
这个配置类一开始是设置密钥库的路径和密码,作用是让 SpringBoot 应用可以根据该 trustStore 中保存的证书去信任目标服务器(Elasticsearch 服务器)的 SSL 证书。
但是后面测试为了方便使用了http协议发送请求,所以就没有用到ssl自签名证书。
在这篇文章的测试中,并没有用到这个配置类。
package cn.ljh.restclient.config;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.boot.autoconfigure.elasticsearch.RestClientBuilderCustomizer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.File;
/**
* author JH 2024-02
* trustStore 是一个专门存密钥的一个库 ,这里只用来存 Elasticsearch 的公钥证书,所以把这个密钥库叫: elastic.store
*/
@Configuration(proxyBeanMethods = false)
public class ElasticsearchConfig
{
//设置密钥库的路径和密码,作用是让 SpringBoot 应用可以根据该 trustStore 中保存的证书去信任目标服务器(Elasticsearch 服务器)的 SSL 证书
// static
// {
// // 获取elastic.store的保存位置
// String storePath = new File(
// ApplicationContext.class
// .getResource("/")
// .getFile()
// )
// .getParentFile()
// .getAbsolutePath() + "\\classes\\elastic.store";
//
// // 设置trustStore的位置,设置要信任的密钥库的路径
// System.setProperty("javax.net.ssl.trustStore", storePath);
//
// // 设置trustStore的读取密码
// System.setProperty("javax.net.ssl.trustStorePassword", "123456");
// }
//对 RestClientBuilderCustomizer 进行定制,主要是为了设置验证目标服务器的证书时,不验证主机名
@Bean
public RestClientBuilderCustomizer restClientBuilderCustomizer()
{
return new RestClientBuilderCustomizer()
{
@Override
public void customize(RestClientBuilder builder)
{
//此处可对 RestClientBuilder 进行定制
}
@Override
public void customize(HttpAsyncClientBuilder builder)
{
// 对 HttpAsyncClientBuilder 进行定制
// 因为此时演示的Elasticsearch 目标服务器的主机地址,就是本机的 IP 地址,
// 所以验证目标服务器的证书时,这台服务器的主机名依然无法通过证书验证
// 设置验证目标服务器的证书时,不验证主机名
builder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE);
}
@Override
public void customize(RequestConfig.Builder builder)
{
//此处可对 RequestConfig.Builder 进行定制
}
};
}
}
application.properties 配置文件
# 配置Elasticsearch的连接
# 指定ElasticSearch服务器的地址(可以列出多个节点的地址)
spring.elasticsearch.rest.uris=http://127.0.0.1:9200
spring.elasticsearch.rest.read-timeout=10s
# 配置用户名和密码
spring.elasticsearch.rest.username=elastic
spring.elasticsearch.rest.password=123456
RestHighLevelClientTest 测试类代码演示
package cn.ljh.restclient;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.SneakyThrows;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
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.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.client.indices.GetIndexResponse;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.json.JSONArray;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Arrays;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class RestHighLevelClientTest
{
//用来操作 Elasticsearch 服务器的一个客户端对象类
@Autowired
private RestHighLevelClient restHLClient;
//创建三个索引库
@ParameterizedTest //参数测试
@SneakyThrows
@ValueSource(strings = {"books", "items", "users"})
public void testCreateIndex(String indexName)
{
//指定分词器创建索引库的json格式的数据,每一行用双引号包起来,然后里面的每个双引号前面用反斜杠\转义
String json = "{" +
"\"settings\": {" +
" \"analysis\": {" +
" \"analyzer\": {" +
" \"default\": {" +
" \"tokenizer\": \"ik_max_word\"" +
" }" +
" }" +
" }" +
" }" +
"}";
CreateIndexRequest request = new CreateIndexRequest(indexName)
//参数1:指定创建索引库时要传入的参数 ; 参数2:指定传入内容的类型
.source(json, XContentType.JSON);
//创建索引库后返回的响应类型--CreateIndexResponse
CreateIndexResponse resp = restHLClient.indices().create(request, RequestOptions.DEFAULT);
//获取Elasticsearch服务器的响应,就是响应索引库是否创建成功
System.err.println(resp.isAcknowledged());
}
//删除索引库
@SneakyThrows
@ParameterizedTest
@ValueSource(strings = {"items", "users"})
public void testDeleteIndex(String indexName)
{
//删除索引的请求数据
DeleteIndexRequest request = new DeleteIndexRequest(indexName);
//客户端调用操作索引的方法,然后再调用删除的方法
AcknowledgedResponse resp = restHLClient.indices().delete(request, RequestOptions.DEFAULT);
//查看删除后的响应
System.err.println(resp.isAcknowledged());
}
//查询所有的索引库
@SneakyThrows
@Test //这个测试不需要参数,直接用这个@Test注解即可
public void testGetIndex()
{
//参数 "*" : 表示匹配所有的索引库
GetIndexRequest request = new GetIndexRequest("*");
//用rest客户端的方法来查询
GetIndexResponse resp = restHLClient.indices().get(request, RequestOptions.DEFAULT);
//返回的索引库是一个String类型的数组
String[] indices = resp.getIndices();
//把数组转成字符串
String s = Arrays.toString(indices);
System.err.println(s);
}
//往索引库添加文档
@ParameterizedTest
@SneakyThrows
//测试参数有多个值 ,用这个注解
@CsvSource({
"1,火影忍者,旋涡鸣人成长为第七代火影的故事,150",
"2,家庭教师,废材纲成长为十代首领的热血事迹,200",
"4,七龙珠Z,超级赛亚人贝吉塔来到地球后的热闹景象,400"
})
public void testSaveDocument(Integer id, String title, String description, Double price)
{
//表明向 books 索引库添加文档
IndexRequest request = new IndexRequest("books")
.id(id + "")
.source(
"title", title,
"description", description,
"price", price
);
IndexResponse resp = restHLClient.index(request, RequestOptions.DEFAULT);
System.err.println(resp);
}
//根据文档的id获取文档
@SneakyThrows
@ParameterizedTest
@ValueSource(ints = {1, 3})
public void testGetDocumentById(Integer id)
{
//表明从 books 索引库获取文档
GetRequest request = new GetRequest("books")
//表明根据指定的文档的id获取文档
.id(id + "");
GetResponse resp = restHLClient.get(request, RequestOptions.DEFAULT);
System.err.println(resp);
}
//根据条件查询文档(普通关键字查询和通配符查询)
@SneakyThrows
@ParameterizedTest
@CsvSource({
"description,热*",
"description,成长"
})
public void testSearchDocument(String field, String term)
{
// 构建查询条件的类
SearchSourceBuilder builder = new SearchSourceBuilder();
// 通过 SearchSourceBuilder 可以用面向对象的方式来构建查询的 JSON 字符串
// SearchSourceBuilder 需要传入 QueryBuilders,而 QueryBuilders 用于构建 QueryBuilder
if (term != null && term.contains("*"))
{
//根据字段和通配符关键字查询
builder.query(QueryBuilders.wildcardQuery(field, term));
} else
{
//根据字段和普通关键字查询
builder.query(QueryBuilders.matchQuery(field,term));
}
//表明从 books 索引库查询文档
SearchRequest request = new SearchRequest("books")
// 此处的 builder 参数用于构建查询语法
.source(builder);
//客户端调用查询的方法 , 参数1:查询条件语法 参数2:默认的请求选项,比如超时时间之类的
SearchResponse resp = restHLClient.search(request, RequestOptions.DEFAULT);
System.err.println(resp);
}
//根据 id 删除文档
@ParameterizedTest
@SneakyThrows
@ValueSource(ints = {3,4})
public void testDeleteDocumentById(Integer id)
{
//表明从 books 索引库删除文档
DeleteRequest request = new DeleteRequest("books")
//获取指定id的文档
.id(id+"");
//rest客户端调用删除文档的方法
DeleteResponse resp = restHLClient.delete(request, RequestOptions.DEFAULT);
System.err.println(resp);
}
}
pom.xml 依赖文件
主要是这个 Elasticsearch 的依赖,其它的就是正常的boot项目需要的依赖
<!-- 添加 HighLevelRest Client -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.12.0</version>
</dependency>
完整依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
</parent>
<groupId>cn.ljh</groupId>
<artifactId>restclient</artifactId>
<version>1.0.0</version>
<name>restclient</name>
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 添加 HighLevelRest Client -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.12.0</version>
</dependency>
<!-- 开发者工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>