ElasticSearch回顾3-SpirngBoot整合ES
本文已参与「新人创作礼」活动,一起开启掘金创作之路。
本篇我们熟悉一下ES在Java中的操作,并将ES整合在SpringBoot中
首先贴官网API地址
API创建索引及文档
去官网找一圈
找到Elasticsearch Clients(这个就是客户端api文档)
这里我们用JavaRest风格的API,我们可以根据自己的语言环境来选择不同的API
选择Java后,我们又发现Java分了两种
一种是high level 和 low level,我们选择high level下的Getting started
找到Maven依赖和基本配置
关于Java Rest Client的说明
Java REST Client 有两种风格:
Java Low Level REST Client :用于Elasticsearch的官方低级客户端。它允许通过http与Elasticsearch 集群通信。将请求编排和响应反编排留给用户自己处理。它兼容所有的Elasticsearch版本。(PS:学过 WebService的话,对编排与反编排这个概念应该不陌生。可以理解为对请求参数的封装,以及对响应结 果的解析)
Java High Level REST Client :用于Elasticsearch的官方高级客户端。它是基于低级客户端的,它提供 很多API,并负责请求的编排与响应的反编排。(PS:就好比是,一个是传自己拼接好的字符串,并且 自己解析返回的结果;而另一个是传对象,返回的结果也已经封装好了,直接是对象,更加规范了参数 的名称以及格式,更加面对对象一点) (PS:所谓低级与高级,我觉得一个很形象的比喻是,面向过程编程与面向对象编程)
项目整合
新建项目
新建一个SpringBoot项目,导入web依赖和elastic依赖
如果忘了也没关系,在pom中加入即可
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
因为SpringBoot默认的配置版本不匹配,我们要自己手动配置自己的ES版本
<elasticsearch.version>7.8.0</elasticsearch.version>
继续查看文档API,
我们发现这里要我们构建一个RestHighLevel的对象,那就整吧
创建配置类
ElasticsearchClientConfig.java
package com.feng.util;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* <h3>springboot-elasticsearch-test</h3>
* <p></p>
*
* @author : Nicer_feng
* @date : 2020-10-21 09:13
**/
@Configuration
public class ElasticsearchClientConfig {
@Bean
public RestHighLevelClient restHighLevelClient(){
RestClientBuilder restClientBuilder;
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("127.0.0.1",9200,"http")));
return client;
}
}
ESUtil.java
package com.feng.util;
import com.alibaba.fastjson.JSON;
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.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* <h3>springboot-elasticsearch-test</h3>
* <p></p>
*
* @author : Nicer_feng
* @date : 2020-10-21 09:19
**/
public class ESUtils<T> {
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
/**
* 判断索引是否存在
* @param index
* @return
* @throws IOException
*/
public boolean existsIndex(String index) throws IOException {
GetIndexRequest request = new GetIndexRequest(index);
boolean exists = client.indices().exists(request,
RequestOptions.DEFAULT);
return exists;
}
/**
* 删除索引
* @param index
* @return
* @throws IOException
*/
public boolean deleteIndex(String index) throws IOException {
DeleteIndexRequest deleteIndexRequest = new
DeleteIndexRequest(index);
AcknowledgedResponse response =
client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
return response.isAcknowledged();
}
/**
* 判断某索引下文档id是否存在
* @param index
* @param id
* @return
* @throws IOException
*/
public boolean docExists(String index, String id) throws IOException {
GetRequest getRequest = new GetRequest(index,id);
//只判断索引是否存在不需要获取_source
getRequest.fetchSourceContext(new FetchSourceContext(false));
getRequest.storedFields("_none_");
boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
return exists;
}
/**
* 添加文档记录
* @param index
* @param id
* @param t 要添加的数据实体类
* @return
* @throws IOException
*/
public boolean addDoc(String index,String id,T t) throws IOException {
IndexRequest request = new IndexRequest(index);
request.id(id);
//timeout
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
request.source(JSON.toJSONString(t), XContentType.JSON);
IndexResponse indexResponse = client.index(request,
RequestOptions.DEFAULT);
RestStatus Status = indexResponse.status();
return Status==RestStatus.OK||Status== RestStatus.CREATED;
}
/**
* 根据id来获取记录
* @param index
* @param id
* @return
* @throws IOException
*/
public GetResponse getDoc(String index, String id) throws IOException {
GetRequest request = new GetRequest(index,id);
GetResponse getResponse = client.get(request,
RequestOptions.DEFAULT);
return getResponse;
}
/**
* 批量添加文档记录
* 没有设置id ES会自动生成一个,如果要设置 IndexRequest的对象.id()即可
* @param index
* @param list
* @return
* @throws IOException
*/
public boolean bulkAdd(String index, List<T> list) throws IOException {
BulkRequest bulkRequest = new BulkRequest();
//timeout
bulkRequest.timeout(TimeValue.timeValueMinutes(2));
bulkRequest.timeout("2m");
for (int i =0;i<list.size();i++){
bulkRequest.add(new IndexRequest(index)
.source(JSON.toJSONString(list.get(i))));
}
BulkResponse bulkResponse = client.bulk(bulkRequest,
RequestOptions.DEFAULT);
return !bulkResponse.hasFailures();
}
/**
* 批量删除和更新就不写了可根据上面几个方法来写
*/
/**
* 更新文档记录
* @param index
* @param id
* @param t
* @return
* @throws IOException
*/
public boolean updateDoc(String index,String id,T t) throws IOException
{
UpdateRequest request = new UpdateRequest(index,id);
request.doc(JSON.toJSONString(t));
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
UpdateResponse updateResponse = client.update(
request, RequestOptions.DEFAULT);
return updateResponse.status()==RestStatus.OK;
}
/**
* 删除文档记录
* @param index
* @param id
* @return
* @throws IOException
*/
public boolean deleteDoc(String index,String id) throws IOException {
DeleteRequest request = new DeleteRequest(index,id);
//timeout
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
DeleteResponse deleteResponse = client.delete(
request, RequestOptions.DEFAULT);
return deleteResponse.status()== RestStatus.OK;
}
/**
* 根据某字段来搜索
* @param index
* @param field
* @param key 要收搜的关键字
* @throws IOException
*/
public void search(String index,String field ,String key,Integer
from,Integer size) throws IOException {
SearchRequest searchRequest = new SearchRequest(index);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.termQuery(field, key));
//控制搜素
sourceBuilder.from(from);
sourceBuilder.size(size);
//最大搜索时间。
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = client.search(searchRequest,
RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(searchResponse.getHits()));
}
}
这里注意pom中导入alibaba的fastjson类
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.74</version>
</dependency>
测试
然后我们测试创建索引
创建索引
package com.feng;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
@SpringBootTest
class SpringbootElasticsearchTestApplicationTests {
@Autowired
RestHighLevelClient restHighLevelClient;
@Test
void contextLoads() throws IOException {
//1、索引创建
CreateIndexRequest request = new CreateIndexRequest("feng_index1");
//2、执行请求 ==> 请求后获取响应
CreateIndexResponse createIndexResponse
= restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
System.out.println(createIndexResponse);
}
}
成功运行并创建索引
获取索引
@Test
void testExistsIndex() throws IOException {
GetIndexRequest request = new GetIndexRequest("feng_index1");
boolean exists = restHighLevelClient.indices().exists(request,
RequestOptions.DEFAULT);
System.out.println(exists);
}
测试存在
删除索引
@Test
void testDeleteIndexRequest() throws IOException {
DeleteIndexRequest deleteIndexRequest = new
DeleteIndexRequest("feng_index1");
AcknowledgedResponse response
= restHighLevelClient.indices().delete(deleteIndexRequest,
RequestOptions.DEFAULT);
System.out.println(response.isAcknowledged());
}
测试,返回true,且刷新后 feng_index1消失
如果我们要添加文档记录呢?
添加文档
首先创建一个实体类
User.java
package com.feng.dao;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;
/**
* <h3>springboot-elasticsearch-test</h3>
* <p></p>
*
* @author : Nicer_feng
* @date : 2020-10-21 13:45
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
public class User {
private String name;
private int age;
}
lombok插件别再问了
测试类
@Test
void testAddDocument() throws IOException {
// 创建对象
User user = new User("冯半仙", 6);
// 创建请求
IndexRequest request = new IndexRequest("feng_index1");
// 规则
request.id("1");
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
request.source(JSON.toJSONString(user), XContentType.JSON);
// 发送请求
IndexResponse indexResponse = restHighLevelClient.index(request,
RequestOptions.DEFAULT);
System.out.println(indexResponse.toString());
RestStatus Status = indexResponse.status();
System.out.println(Status == RestStatus.OK || Status ==
RestStatus.CREATED);
}
运行成功发现
判断索引下文档id是否存在
// 判断此id是否存在这个索引库中
@Test
void testIsExists() throws IOException {
GetRequest getRequest = new GetRequest("feng_index1","1");
// 不获取_source上下文 storedFields
getRequest.fetchSourceContext(new FetchSourceContext(false));
getRequest.storedFields("_none_");
// 判断此id是否存在!
boolean exists = restHighLevelClient.exists(getRequest,
RequestOptions.DEFAULT);
System.out.println(exists);
}
查询1和2分别返回结果true和false
根据id查询记录
// 获得文档记录
@Test
void testGetDocument() throws IOException {
GetRequest getRequest = new GetRequest("feng_index1","1");
GetResponse getResponse = restHighLevelClient.get(getRequest,
RequestOptions.DEFAULT);
System.out.println(getResponse.getSourceAsString()); // 打印文档内容
System.out.println(getResponse);
}
运行结果
更新文档记录
// 更新文档记录
@Test
void testUpdateDocument() throws IOException {
UpdateRequest request = new UpdateRequest("feng_index1","1");
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
User user = new User("冯半仙996", 18);
request.doc(JSON.toJSONString(user), XContentType.JSON);
UpdateResponse updateResponse = restHighLevelClient.update(
request, RequestOptions.DEFAULT);
System.out.println(updateResponse.status() == RestStatus.OK);
}
当然更新成功
删除文档记录
// 删除文档测试
@Test
void testDelete() throws IOException {
DeleteRequest request = new DeleteRequest("feng_index1","3");
//timeout
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
DeleteResponse deleteResponse = restHighLevelClient.delete(
request, RequestOptions.DEFAULT);
System.out.println(deleteResponse.status() == RestStatus.OK);
}
记得先插一个3,再删除哈
批量添加数据
// 批量添加数据
@Test
void testBulkRequest() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
//timeout
bulkRequest.timeout(TimeValue.timeValueMinutes(2));
bulkRequest.timeout("2m");
ArrayList<User> userList = new ArrayList<>();
userList.add(new User("feng1",3));
userList.add(new User("feng2",3));
userList.add(new User("feng3",3));
userList.add(new User("banxian1",3));
userList.add(new User("banxian2",3));
userList.add(new User("banxian3",3));
for (int i =0;i<userList.size();i++){
bulkRequest
.add(new IndexRequest("feng_index1")
.id(""+(i+1))
.source(JSON.toJSONString(userList.get(i)),XContentType.JSON));
}
// bulk
BulkResponse bulkResponse =
restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
System.out.println(!bulkResponse.hasFailures());
}
运行后发现数据成功插入
查询测试
// 查询测试
/**
* 使用QueryBuilder
* termQuery("key", obj) 完全匹配
* termsQuery("key", obj1, obj2..) 一次匹配多个值
* matchQuery("key", Obj) 单个匹配, field不支持通配符, 前缀具高级特性
* multiMatchQuery("text", "field1", "field2"..); 匹配多个字段, field有通
配符忒行
* matchAllQuery(); 匹配所有文件
*/
@Test
void testSearch() throws IOException {
SearchRequest searchRequest = new SearchRequest("feng_index1");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name","qinjiang1");
MatchAllQueryBuilder matchAllQueryBuilder =
QueryBuilders.matchAllQuery();
sourceBuilder.query(matchAllQueryBuilder);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
searchRequest.source(sourceBuilder);
SearchResponse response = restHighLevelClient.search(searchRequest,
RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(response.getHits()));
System.out.println("================SearchHit==================");
for (SearchHit documentFields : response.getHits().getHits()) {
System.out.println(documentFields.getSourceAsMap());
}
}
运行后