文章目录
前言
ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES,其中的Java Rest Client又包括两种:
- Java Low Level Rest Client
- Java High Level Rest Client
本文介绍的是Java HighLevel Rest Client客户端API;
一、环境准备
在elasticsearch提供的API中,与elasticsearch一切交互都封装在一个名为RestHighLevelClient的类
中,必须先完成这个对象的初始化,建立与elasticsearch的连接。
1)引入es的RestHighLevelClient依赖:
java
dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
2)初始化RestHighLevelClient:
这里为了单元测试方便,我们创建一个测试类HotelIndexTest,然后将初始化的代码编写在
@BeforeEach方法中:
java
/**
* @author 杨树林
* @version 1.0
* @since 12/8/2023
*/
@SpringBootTest
class HotelIndexTest{
private RestHighLevelClient client;
@BeforeEach
void setUp(){
this.client=new RestHighLevelClient(RestClient.builder
(HttpHost.create("http://localhost:9200")));
}
@AfterEach
void tearDown() throws IOException {
this.client.close();
}
}
3)创建HotelConstants类,定义mapping映射的JSON字符串常量
java
public class HotelConstants {
public static final String MAPPING_TEMPLATE = "{\n" +
" \"mappings\": {\n" +
" \"properties\": {\n" +
" \"id\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"name\":{\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\",\n" +
" \"copy_to\": \"all\"\n" +
" },\n" +
" \"address\":{\n" +
" \"type\": \"keyword\",\n" +
" \"index\": false\n" +
" },\n" +
" \"price\":{\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"score\":{\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"brand\":{\n" +
" \"type\": \"keyword\",\n" +
" \"copy_to\": \"all\"\n" +
" },\n" +
" \"city\":{\n" +
" \"type\": \"keyword\",\n" +
" \"copy_to\": \"all\"\n" +
" },\n" +
" \"starName\":{\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"business\":{\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"location\":{\n" +
" \"type\": \"geo_point\"\n" +
" },\n" +
" \"pic\":{\n" +
" \"type\": \"keyword\",\n" +
" \"index\": false\n" +
" },\n" +
" \"all\":{\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\"\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
}
二、RsetAPI操作索引库
编写单元测试,实现一下功能:
1.创建索引库
java
@Test
void creatHotelIndex() throws IOException {
//1、创建Requset对象
CreateIndexRequest request = new CreateIndexRequest("hotels");
//2、准备请求的参数:DEL语句
request.source(HotelConstants.MAPPING_TEMPLATE, XContentType.JSON);
//3、发起请求
client.indices().create(request,RequestOptions.DEFAULT);
}
2.判断索引库是否存在
java
@Test
void testExistsHotelIndex() throws IOException {
//1、创建Requset对象
GetIndexRequest request = new GetIndexRequest("hotels");
//2、发起请求
boolean isExists = client.indices().exists(request,RequestOptions.DEFAULT);
System.err.println(isExists ? "索引库已经存在!" : "索引库不存在!");
}
3.删除索引库
java
@Test
void delHotelIndex() throws IOException {
//1、创建Requset对象
DeleteIndexRequest request = new DeleteIndexRequest("hotels");
//2、发起请求
client.indices().delete(request,RequestOptions.DEFAULT);
}
二、RsetAPI操作文档
1.新增文档
java
@Autowired
HotelServiceImpl service;
@Test
void addDocument() throws IOException {
// 1.根据id查询酒店数据
Hotel hotel = service.getById("36934");
// 2.转换为文档类型
HotelDoc hotelDoc = new HotelDoc(hotel);
// 3.将HotelDoc转json
String json = JSON.toJSONString(hotelDoc);
IndexRequest request = new IndexRequest("hotels").id(hotelDoc.getId().toString());
request.source(json, XContentType.JSON);
client.index(request, RequestOptions.DEFAULT);
}
2.单条查询
java
@Test
void getDocument() throws IOException {
GetRequest request = new GetRequest("hotels","36934");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
String json = response.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json,HotelDoc.class);
System.out.println(hotelDoc);
}
3.删除文档
java
@Test
void delDocument() throws IOException {
DeleteRequest request = new DeleteRequest("hotels","36934");
client.delete(request,RequestOptions.DEFAULT);
}
4.增量修改
api中全局修改与新增一致
java
@Test
void UpdateDocument() throws IOException {
UpdateRequest request = new UpdateRequest("hotels", "36934");
request.doc(
"name","XX酒店",
"city","西安",
"price", "200000",
"starName", "八星级"
);
client.update(request, RequestOptions.DEFAULT);
}
5.批量导入
java
@Test
void addBulkRequest() throws IOException {
//查询所有酒店信息
List<Hotel> hotels = service.list();
//1.创建request
BulkRequest request = new BulkRequest();
for (Hotel hotel : hotels) {
HotelDoc hotelDoc = new HotelDoc(hotel);
request.add(new IndexRequest("hotels")
.id(hotelDoc.getId().toString())
.source(JSON.toJSONString(hotelDoc),XContentType.JSON));
}
client.bulk(request,RequestOptions.DEFAULT);
}
6.自定义响应解析方法
java
void show(SearchResponse response){
//解析响应
SearchHits searchHits =response.getHits();
//获取总条数
Long total = searchHits.getTotalHits().value;
System.out.println("共搜到"+total+"条数据");
//文档数组
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
String json = hit.getSourceAsString();
System.err.println(json);
HotelDoc hotelDoc = JSON.parseObject(json,HotelDoc.class);
System.out.println(hotelDoc);
}
}
四、常用的查询方法
1.MatchAll():查询所有
java
@Test
void testMatchAll() throws IOException {
//1.准备request
SearchRequest request = new SearchRequest("hotels");
//2、准备DEl,QueryBuilders构造查询条件
request.source().query(QueryBuilders.matchAllQuery());
//3.执行查询,返回响应结果
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//4.解析响应
show(response);
}
2.matchQuery():单字段查询
java
@Test
void testMatch() throws IOException {
//1.准备request
SearchRequest request = new SearchRequest("hotels");
// 2.准备DSL 参数1:字段 参数2:数据
request.source().query(QueryBuilders.matchQuery("all","如家"));
//3.执行查询,返回响应结果
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//4.解析响应
show(response);
}
3.multiMatchQuery():多字段查询
java
@Test
void testMultiMatch() throws IOException {
//1.准备request
SearchRequest request = new SearchRequest("hotels");
// 2.准备DSL
request.source().query(QueryBuilders.multiMatchQuery("如家","name","business"));
//3.执行查询,返回响应结果
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//4.解析响应
show(response);
}
4.termQuery():词条精确值查询
java
@Test
void testTermQuery() throws IOException {
//1.准备request
SearchRequest request = new SearchRequest("hotels");
// 2.准备DSL
request.source().query(QueryBuilders.termQuery("city","上海"));
//3.执行查询,返回响应结果
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//4.解析响应
show(response);
}
5.rangeQuery():范围查询
java
@Test
void testRangeQuery() throws IOException {
//1.准备request
SearchRequest request = new SearchRequest("hotels");
// 2.准备DSL
request.source().query(QueryBuilders.rangeQuery("pirce").gte(100).lte(200));
//3.执行查询,返回响应结果
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//4.解析响应
show(response);
}
6.bool复合查询
布尔查询是一个或多个查询子句的组合,子查询的组合方式有:
must :必须匹配每个子查询,类似"与";
should :选择性匹配子查询,类似"或";
must_not :必须不匹配,不参与算分,类似"非";
filter :必须匹配,类似"与",不参与算分一般搜索框用must,选择条件使用filter;
java
@Test
void testBool() throws IOException {
SearchRequest request = new SearchRequest("hotels");
//方式1
// BoolQueryBuilder boolQuery = new BoolQueryBuilder();
// boolQuery.must(QueryBuilders.termQuery("city","上海"));
// boolQuery.filter(QueryBuilders.rangeQuery("price").gte(100).lte(200));
// request.source().query(boolQuery);
//方式2
request.source().query(new BoolQueryBuilder()
.must(QueryBuilders.termQuery("city","上海"))
.filter(QueryBuilders.rangeQuery("price").gte(100).lte(200)));
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
show(response);
}
7.分页查询
java
@Test
void testPageAndSort() throws IOException {
int page = 1, size = 5;
String searchName = "如家";
SearchRequest request = new SearchRequest("hotels");
// 2.1.query
if(searchName == null){
request.source().query(QueryBuilders.matchAllQuery());
}else{
request.source().query(QueryBuilders.matchQuery("name", searchName));
}
// 2.2.分页 from、size
request.source().from((page - 1) * size).size(size);
//2.3.排序
request.source().sort("price", SortOrder.DESC);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
show(response);
}