spring-data-elasticsearch:transport-api.jar
说明:springboot 版本不同, transport-api.jar 不同,不能适配 es 版本
7.x 已经不建议使用,8 以后就要废弃
Elasticsearch-Rest-Client:官方 RestClient,封装了 ES 操作,API 层次分明,上手简单(推荐)
小编安装的Elasticsearch版本是7.4.2所以版本要对应依赖版本也要是7.4.2
<!-- elasticsearch-java restful client 操作http -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.2</version>
</dependency>
要注意的一点是springboot默认会引入spring-data-elasticsearch
所以我们也要将其版本改成和我们对应的版本
<properties>
<java.version>1.8</java.version>
<!-- 这个是spring data 默认支持的。改成和我们自己配置的版本一致-->
<elasticsearch.version>7.4.2</elasticsearch.version>
</properties>
package com.atguigu.gulimall.search.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author suqinyi
* @Date 2021/5/23
*/
/**
* 1、导入依赖
* 2、编写配置
* 3、参照API文档
*/
@Configuration
public class GulimallElasticSearchConfig {
public static final RequestOptions COMMON_OPTIONS;
static {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
// builder.addHeader("Authorization", "Bearer " + TOKEN);
// builder.setHttpAsyncResponseConsumerFactory(
// new HttpAsyncResponseConsumerFactory
// .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
COMMON_OPTIONS = builder.build();
}
//注入client
@Bean
public RestHighLevelClient esRestClient() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("192.168.56.10", 9200, "http")
)
);
return client;
}
}
说明:如果在对这个users(名称叫索引)添加数据,那么不会报错,他的版本号会加上去(变化),所以是添加更新二合一
package com.atguigu.gulimall.search;
import com.alibaba.fastjson.JSON;
import com.atguigu.gulimall.search.config.GulimallElasticSearchConfig;
import lombok.Data;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
@RunWith(SpringRunner.class)//指定spring的驱动
@SpringBootTest//小编的springboot版本是2.18 说明:2.x和1.x的版本测试类有着区别
public class GulimallSearchApplicationTests {
@Autowired
private RestHighLevelClient client;
/**
* 测试存储数据到es
* 更新也可以
*/
@Test
public void indexData() throws IOException {
IndexRequest indexRequest = new IndexRequest("users");
//数据的id-不设置就自动生成,类型string
indexRequest.id("1");
// 方式一:
//indexRequest.source("username","zhangsan","age",18,"gender","男");
// 方式二(推荐):
User user = new User();
user.setAge(18);
user.setUsername("zhangsan");
user.setGender("男");
String jsonString = JSON.toJSONString(user);
indexRequest.source(jsonString, XContentType.JSON);
//调用,执行操作
IndexResponse index = client.index(indexRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);
//提取有用的数据
System.out.println("响应数据:"+"\n"+index);
}
@Data//使用lombok插件+依赖
class User{
private String username;
private String gender;
private Integer age;
}
//测试容器是否注入成功
@Test
public void testIfOK() {
System.out.println(client);
}
}
更具体的看官方文档示例
/**
*查询-条件检索
*/
@Test
public void searchData() throws IOException {
//创建检索请求
SearchRequest searchRequest = new SearchRequest();
//指定索引
searchRequest.indices("users");
//指定DSL,检索条件
//SearchSourceBuilder sourceBuilder 封装检索条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//构造检索条件
sourceBuilder.query(QueryBuilders.matchQuery("username","zhangsan"));
// sourceBuilder.from();
// sourceBuilder.size();
// sourceBuilder.aggregation();//这个是聚合
System.out.println("检索条件:"+"\n"+sourceBuilder);
searchRequest.source(sourceBuilder);
//执行检索
SearchResponse searchResponse = client.search(searchRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);
//分析结果
System.out.println(searchResponse.toString());
SearchHits hits = searchResponse.getHits();
SearchHit[] hits1 = hits.getHits();//真正的命中数据--可以进行遍历操作
for (SearchHit hit : hits1) {
// System.out.println(hit);
// System.out.println(hit.xxx);
//一般要处理的都是source里面的数据 ==> 通常是将其转成string,在和实体类映射起来
String string = hit.getSourceAsString();
//利用json工具将string转成实体类:以fastJson为例,jackson也行
User01 User = JSON.parseObject(string, User01.class);
System.out.println("user:"+User);
}
//获取聚合数据--这边小编没准备复杂数据,就没聚合了。这边贴个官方图
}
//使用lombok插件+依赖
@ToString
@Data
static class User01{
private String username;
private String gender;
private Integer age;
}
在项目中通常的操作
说明:
索引是user
里面有userId还有个对象student包含着age和name的字段
所以:在java中创建的实体类的属性名和类型要和这个索引里面的字段对应起来,在操作的时候将实体类转成json,插入es才不会有问题
PUT user
{
"mappings": {
"properties": {
"skuId": {
"type": "long"
},
"student": {
"type": "nested",
"properties": {
"age": {
"type": "long"
},
"name": {
"type": "keyword"
}
}
}
}
}
}
//注入
@Autowired
RestHighLevelClient restHighLevelClient;
//业务的核心代码
@Override
public boolean saveToEs(List<SkuEsModel> skuEsModels) throws IOException {
/**
* 说明:
* 传入的List skuEsModels 是一个list
* 里面有多个SkuEsModel(实体类)和elasticsearch创建的索引(名称和类型)对应
* 如果不明白。。在看下小编上面写的那个基础整合案例,里面的User
*/
//保存到es
//给es中建立索引,user,建立映射关系
//SkuEsModel这个实体类的属性名和类型和user索引的数据对应起来
//给es中保存数据
//源码里面需要的俩个属性:BulkRequest bulkRequest, RequestOptions optionss
//批量插入
BulkRequest bulkRequest = new BulkRequest();
//遍历
for (SkuEsModel model : skuEsModels) {
// 构造保存请求
IndexRequest indexRequest = new IndexRequest(EsConstant.PRODUCT_INDEX);
//设置id的话可以保证不会加入相同的数据,数据存在会采用更新
indexRequest.id(model.getSkuId().toString());
//将数据转成Json。 这边用的是fastjson
String jsonString = JSON.toJSONString(model);
indexRequest.source(jsonString, XContentType.JSON);
bulkRequest.add(indexRequest);
}
//restHighLevelClient.bulk()这个采用是同步,里面也有个异步的方法 restHighLevelClient.bulkAsync();
BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);
// TODO 如果批量错误,待处理问题
// 有错误是true,没有是false
boolean b = bulk.hasFailures();
//stream流的写法,看不懂的去看下java8新特性
List<String> collect = Arrays.stream(bulk.getItems()).map(item -> {
return item.getId();
}).collect(Collectors.toList());
log.info("数据,{},es返回数据{}",collect,bulk.toString());
return b;
}
如果有不同意见可以留言评论
更加详细的操作看官网文档的示例啦
其实如果安装的是elasticsearch6.x版本
使用spring-data-elasticsearch:transport-api.jar也非常便捷
对于elasticsearch版本的升级要慎重