终于到应用方面了,这里实现整合有两种方式,一种是通过客户端整合,即本文说的一种方式,一种是使用springData,不得不说spring是真的强,其实这个有点像redis的整合,貌似也有两种一种通过jedis,一种通过springdata,下面记录一下client整合的方式
这里采用官方推荐的client
下面进行整合
在idea创建一个springboot工程,并引入依赖
<?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 http://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.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.gdut.imis</groupId>
<artifactId>es-client-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>es-client-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.1.1</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.1</version>
</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>
</plugin>
</plugins>
</build>
</project>
新建配置类,向容器注册gson对象和客户端对象
package com.gdut.imis.esclientdemo.config;
import com.google.gson.Gson;
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;
/**
* @author lulu
* @Date 2019/6/7 18:27
*/
@Configuration
public class EsConfig {
@Bean
public Gson gson(){
return new Gson();
}
@Bean
public RestHighLevelClient client(){
RestHighLevelClient client=new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost",9200,"http")
//这里如果要用client去访问其他节点,就添加进去
)
);
return client;
}
}
然后编写通过id获取的方法
@GetMapping("/order/getById/{id}")
public Map<String,Object> getOrder(@PathVariable("id")String id){
GetRequest getRequest=new GetRequest("order","_doc",id);
Map map=new HashMap();
GetResponse response=null;
try{
response= client.get(getRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
if(response.isExists()){
map.put("success",true);
map.put("data",response.getSource());
}else{
map.put("success",false);
}
return map;
}
查看结果
编写新建方法:
这里的新建方法遇到两个坑
第一个:由于版本不同,导致插入某个方法缺失,解决方法是把过时的依赖排除,添加有该方法的依赖,这里的elasticsearch本来为6.4.3,把他排除引入7.0.0的
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.1.1</version>
<exclusions>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.elasticsearch/elasticsearch -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.0.0</version>
</dependency>
第二个:对象数组
对象数组很奇怪,必须以List<Map>的形式才能插入,这里面给出插入的例子供给参考
具体插入代码
@PostMapping("/order/create")
public Map<String,Object> createOrder(@RequestParam("buyer")String buyer,
@RequestParam("date")String date,
@RequestParam("totalPrice")Double total,
@RequestParam("products")String products,
@RequestParam("id")String id
){
Map map=new HashMap();
XContentBuilder builder=null;
IndexRequest request=new IndexRequest("order");
List<Product> productList=gson.fromJson(products,new TypeToken<List<Product>>(){}.getType());
List<Map<String,Object>> list=productList.stream().map(e->{
Map<String,Object> temp=new HashMap<>();
Field [] fields=e.getClass().getDeclaredFields();
for(Field f:fields){
f.setAccessible(true);
try {
temp.put(f.getName(),f.get(e));
} catch (IllegalAccessException e1) {
e1.printStackTrace();
}
}
return temp;
}).collect(Collectors.toList());
try {
builder = XContentFactory.jsonBuilder();
builder.startObject()
.field("buyer",buyer).field("date",date)
.field("totalPrice",total)
.field("products",list)
.endObject()
;
request.id(id).opType("create").source(builder);
IndexResponse response=client.index(request,RequestOptions.DEFAULT);
map.put("status",response.status());
} catch (IOException e) {
e.printStackTrace();
}
return map;
}
结果:
然后到删除接口:
@DeleteMapping("/order/delete/{id}")
public String deleteOrder(@PathVariable("id")String id){
DeleteRequest request=new DeleteRequest("order",id);
try {
DeleteResponse response= client.delete(request,RequestOptions.DEFAULT);
return response.status().name();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
更新,这里的更新如果要更新对象数组也是要和前面的数组插入一样把他转为list<map>
更新前
更新参数:
结果:
代码如下
@PostMapping("/order/update/{id}")
public String update(@PathVariable("id")String id,
@RequestParam(name="buyer",required = false)String buyer,
@RequestParam(name="status",required = false)Integer status) throws IOException {
UpdateRequest request=new UpdateRequest("order",id);
Map<String,Object> temp=new HashMap<>();
if(!ObjectUtils.isEmpty(status)){
temp.put("status",status);
}
if(!ObjectUtils.isEmpty(buyer)){
temp.put("buyer",buyer);
}
request.doc(temp);
return client.update(request,RequestOptions.DEFAULT).status().name();
}
复合查询:
代码如下
@PostMapping("/order/query")
public List<Map<String, Object>> query(@RequestParam(value = "buyer", required = false) String buyer,
@RequestParam(value = "gtePrice", required = false) Double gtePrice,
@RequestParam(value = "value=ltePrice", required = false) Double ltePrice,
@RequestParam(value = "status", required = false) Integer status,
@RequestParam("index") Integer index,
@RequestParam("size") Integer size
) throws IOException {
SearchRequest request = new SearchRequest("order");
//构造bool查询
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
if (!ObjectUtils.isEmpty(buyer)) {
boolQueryBuilder.must(QueryBuilders.matchQuery("buyer", buyer));
}
if (!ObjectUtils.isEmpty(status)) {
boolQueryBuilder.must(QueryBuilders.matchQuery("status", status));
}
//对应filter
if (!ObjectUtils.isEmpty(gtePrice) && !ObjectUtils.isEmpty(ltePrice)) {
boolQueryBuilder.filter(QueryBuilders.rangeQuery("totalPrice").from(ltePrice).to(gtePrice));
}
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//排序
searchSourceBuilder.sort(SortBuilders.fieldSort("totalPrice").order(SortOrder.DESC));
//分页
searchSourceBuilder.from(index).size(size).query(boolQueryBuilder);
request.searchType(SearchType.DEFAULT).source(searchSourceBuilder);
List<Map<String, Object>> list = new ArrayList<>();
for (SearchHit s : client.search(request, RequestOptions.DEFAULT).getHits().getHits()) {
list.add(s.getSourceAsMap());
}
return list;
}
结果
[
{
"date": "2019-04-07 11:14:00",
"totalPrice": "1888",
"buyer": "lele",
"status": 1,
"products": [
{
"price": "1888",
"count": "1",
"name": "人头马",
"category": "酒水类"
}
]
},
{
"date": "2019-02-06 11:14:00",
"totalPrice": "60",
"buyer": "lele",
"status": 1,
"products": [
{
"price": "60.0",
"count": "1",
"name": "母鸡",
"category": "肉类"
}
]
},
{
"date": "2019-05-07 11:14:00",
"totalPrice": "20",
"buyer": "lele",
"status": 1,
"products": [
{
"price": "20.0",
"count": "1",
"name": "波霸奶茶",
"category": "饮料"
}
]
}
]
而批量操作,则是创建批量操作的请求,里面可以可以添加单个请求,比如上述的增删改的操作,举另一个例子
public Boolean batchInsert(Collection<MessageContent> c) {
//批量操作请求:
BulkRequest bulkRequest = new BulkRequest();
for (MessageContent m : c) {
try {
//添加请求,这里不一定是插入,插入+修改+删除组合都可以
bulkRequest.add(new IndexRequest(index).id(m.getMessageId()).source(Object2JsonUtil.ObjectToMap(m)));
BulkResponse r = client.bulk(bulkRequest, RequestOptions.DEFAULT);
if (r.hasFailures()) {
return false;
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
关于client的基本操作暂时到这里,这是项目的github地址,更多api的使用请查阅官方文档,另外一种方式这里就不展示了,只要熟悉jpa用法再看看文档就可以了,具体请查看官方文档,es的入门就到这里,es里面还有很多功能因为个人水平原因在本次学习里面没有提及,里面好多没有用过的api,只能等到时候有需要再去深究,到最后我不得不感叹spring团队太厉害了,一个springdata,感觉和redis、mongodb等nosql和sql用起来没什么大的区别
2019-06-19补充:
我试着用spring data去做spring data elasticsearch兼容的版本还没到最低要求——6.8,于是尝试链接时报错了,
java.lang.IllegalStateException: Received message from unsupported version: [6.4.3] minimal compatible version is: [6.8.0]
今天看的版本对应如下
Spring Data Elasticsearch | Elasticsearch |
---|---|
3.2.x | 6.7.2 |
3.1.x | 6.2.2 |
3.0.x | 5.5.0 |
2.1.x | 2.4.0 |
2.0.x | 2.2.0 |
1.3.x | 1.5.2 |
以后有支持了再更新
2019-10-09补充:
最近发现有了,写了另一篇文章记录:https://blog.csdn.net/weixin_37703281/article/details/102303660