前言
前面学习了一下 使用springboot整合 transport 进行搭建elasticsearch服务,但是transport 以后要被废弃了,所以便来学习一下,rest 整合 springboot 来搭建操作 elasticsearch,这两个很相似,而且 rest 也是 springboot整合。其依赖为
spring-boot-starter-data-elasticsearch
,里面包含了spring-data-elasticsearch
,这里面又包含了elasticsearch-rest-high-level-client
使用了 elasticsearch 6.4.2版本,kibana 6.4.2 版本 elasticsearch-head 三个软件
博客目录
- elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
- elasticsearch学习二:使用springboot整合TransportClient 进行搭建elasticsearch服务
- elasticsearch学习三:elasticsearch-ik分词器的自定义配置 分词内容
- elasticsearch学习四:使用springboot整合 rest 进行搭建elasticsearch服务
一、添加pom依赖
1、 可以在创建项目时添加
2、 可以手动自己添加
<!--导入的 elasticsearch -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
3、 还需要阿里的json依赖包,可以快速转换json
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
4、 修改版本信息
<properties>
<java.version>1.8</java.version>
<!-- 自己定义 es 版本依赖,保证和本地一致-->
<elasticsearch.version>6.4.2</elasticsearch.version>
</properties>
5、 pom.xml 的所有依赖
<?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.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.feng</groupId>
<artifactId>springboot-elasticsearch-rest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-elasticsearch-rest</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<!-- 自己定义 es 版本依赖,保证和本地一致-->
<elasticsearch.version>6.4.2</elasticsearch.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<!--导入的 elasticsearch -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<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>
二、ElasticSearchConfig配置类
package com.feng.config;
import lombok.Data;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "elasticsearch")
public class ElasticSearchConfig {
// @Value("${elasticsearch.hostname}")
private String hostname;
// @Value("${elasticsearch.port}")
private String port;
// @Value("${elasticsearch.scheme}")
private String scheme;
@Bean
public RestHighLevelClient restHighLevelClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost(hostname, Integer.valueOf(port), scheme)));
return client;
}
}
三、pojo类User(测试)
package com.feng.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Component
public class User {
private String name;
private int age;
}
四、application.properties
elasticsearch.hostname = 127.0.0.1
elasticsearch.port = 9200
elasticsearch.scheme = http
五、目录结构
六、测试代码
- 都已测试,并测试通过
- 主要测试了,索引、文档的 CRUD,索引 index 是否存在,搜索(重要),高亮
package com.feng;
import com.alibaba.fastjson.JSON;
import com.feng.bean.User;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
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.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermsQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
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;
@SpringBootTest
class SpringbootElasticsearchRestApplicationTests {
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
@Test
void contextLoads() {
System.out.println("111");
}
// 测试 索引的创建 request
@Test
void testCreateIndex() throws IOException {
// 1、创建索引请求
CreateIndexRequest request = new CreateIndexRequest("feng_index");
// 2、 客户端执行请求 IndicesClient ,请求后获取响应。
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(createIndexResponse);
}
// 测试 索引是否存在, 这里有问题
@Test
void testGetIndex() throws IOException {
//1.创建索引请求
GetIndexRequest getIndexRequest = new GetIndexRequest().indices("feng_index");
boolean exists = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
System.out.println(exists);
}
// 测试 删除索引
@Test
void testDeleteIndex() throws IOException {
//1.创建索引请求
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("feng_index");
DeleteIndexResponse delete = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
System.out.println(delete.isAcknowledged());
}
// 测试 添加文档
@Test
void testCreateDocument() throws IOException {
// 创建对象
User user = new User("冯凡利", 3);
// 创建请求
IndexRequest indexRequest = new IndexRequest("feng_index");
// 规则 put /feng_index/_doc/1
indexRequest.id("1");
indexRequest.type("_doc");
indexRequest.timeout(TimeValue.timeValueSeconds(3000));
indexRequest.timeout("1s");
// 数据放入请求 json
indexRequest.source(JSON.toJSONString(user), XContentType.JSON);
// 客户端发送请求,获取响应的结果
IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(indexResponse.toString()); // IndexResponse[index=feng_index,type=_doc,id=1,version=2,result=updated,seqNo=1,primaryTerm=2,shards={"total":2,"successful":1,"failed":0}]
System.out.println(indexResponse.status()); // 对应命令返回的状态: OK
}
// 获取文档, 判断是否存在 get /index/doc/1
@Test
public void testIsExists() throws IOException {
GetRequest getRequest = new GetRequest("feng_index","_doc", "1");
// 不获取返回的 _source 的上下文
// getRequest.fetchSourceContext(new FetchSourceContext(false));
// getRequest.storedFields("_none_");
boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
System.out.println(exists);
}
// 获取文档信息
@Test
public void testGetDocument() throws IOException {
GetRequest getRequest = new GetRequest("feng_index","_doc", "1");
GetResponse documentFields = client.get(getRequest, RequestOptions.DEFAULT);
System.out.println(documentFields.getIndex()); // feng_index
System.out.println(documentFields.getId()); // 1
System.out.println(documentFields.getSourceAsMap()); // {name=冯凡利, age=3}
System.out.println(documentFields.getSourceAsString()); // 打印文档的内容 {"age":3,"name":"冯凡利"}
System.out.println(documentFields);// 返回的全部内容和命令式一样的 {"_index":"feng_index","_type":"_doc","_id":"1","_version":2,"found":true,"_source":{"age":3,"name":"冯凡利"}}
}
// 更新 文档信息
@Test
public void testUpdateDocument() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("feng_index", "_doc", "1");
updateRequest.timeout("3000S");
User user = new User("冯凡利java", 18);
updateRequest.doc(JSON.toJSONString(user), XContentType.JSON);
UpdateResponse update = client.update(updateRequest, RequestOptions.DEFAULT);
System.out.println(update.getGetResult());
System.out.println(update.status());
}
// 删除 文档信息
@Test
public void testDeleteDocument() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest("feng_index", "_doc", "1");
deleteRequest.timeout("3000s");
DeleteResponse delete = client.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(delete.status()); // ok , 去head中查看,没有文档记录了
}
// 特殊, 真的项目一般都会批量插入数据!!
@Test
public void testBulkDocument() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("10s");
ArrayList<User> userArrayList = new ArrayList<>();
userArrayList.add(new User("fengfanli1", 12));
userArrayList.add(new User("fengfanli2", 12));
userArrayList.add(new User("fengfanli3", 12));
userArrayList.add(new User("fengfanli4", 12));
// 批处理请求
for (int i = 0; i< userArrayList.size(); i++){
// 批量更新和批量删除,就在这里修改对应的请求就可以了
bulkRequest.add(new IndexRequest("feng_index")
.type("_doc")
.id(""+(i+1))
.source(JSON.toJSONString(userArrayList.get(i)), XContentType.JSON));
}
BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println(bulk.hasFailures());// 是否失败, 返回false,代表成功
}
/*
* 查询
* SearchRequest: 搜索请求
* SearchSourceBuilder: 条件构造
* HighlightBuilder: 构建高亮
* TermsQueryBuilder: 精确查询
* MatchAllQueryBuilder:匹配全部
* XXX QueryBuilder:
* */
@Test
public void testSearch() throws IOException{
SearchRequest searchRequest = new SearchRequest("feng_index");
// 构建搜索条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
HighlightBuilder highlightBuilder = new HighlightBuilder();
searchSourceBuilder.highlighter(highlightBuilder);
// 查询条件,我们可以使用 QueryBuilders 工具类来实现
// QueryBuilders.termsQuery() 精确
// QueryBuilders.matchAllQuery() 匹配所有
TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("name", "fengfanli1");
// MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
searchSourceBuilder.query(termsQueryBuilder);
// 构建 分页信息
// searchSourceBuilder.from();
// searchSourceBuilder.size();
searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(searchResponse.getHits()));
// 打印:{"fragment":true,"hits":[{"fields":{},"fragment":false,"highlightFields":{},"id":"1","matchedQueries":[],"score":1.0,"sortValues":[],"sourceAsMap":{"name":"fengfanli1","age":12},"sourceAsString":"{\"age\":12,\"name\":\"fengfanli1\"}","sourceRef":{"childResources":[],"fragment":true},"type":"_doc","version":-1}],"maxScore":1.0,"totalHits":1}
System.out.println("==================================");
for (SearchHit documentFields : searchResponse.getHits().getHits()){
System.out.println(documentFields.getSourceAsMap()); //{name=fengfanli1, age=12}
}
}
}