SpringBoot整合ES-High-Level-Client

  1. 1. 1.建微服务
  2. 2. 2.引入依赖
  3. 3. 3.启动报错
  4. 4. 4.完整pom
  5. 5. 5.配置bootstrap文件
  6. 6. 6.编写ES配置文件
  7. 7. 7. 测试

最近新出来了一个框架GitHub - dromara/easy-es,介绍说类似mybatis-plus写法写es,也许可以抽时间试试🤔。
本笔记基于rest-high-level-client,但是在ES的7.15版本rest-high-level-client现在已经被标记为过时了。推荐使用spring-boot-starter-data-elasticsearch依赖。本篇可以仅作了解。
出现了一个名称为Easy-Es的ORM框架,介绍说使用类似于mybatis-plus,底层使用RestHighLevelClient。

1.建微服务

为ES单独建立一个微服务,模板建立的时候仅选择Spring-web依赖即可,我这里的spring-boot版本选择的2.6.8与其他微服务一致。

2.引入依赖

引入common微服务依赖。

1
2
3
4
5
<dependency>
<groupId>com.example.mall</groupId>
<artifactId>mall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>

引入es依赖

1
2
3
4
5
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.2</version>
</dependency>

指定ES版本,因为是SpringBoot项目,所以ES版本会被SpringBoot版本管理,需要手动改为与自己安装的ES版本一致。按图依次点击即可查看Spring-boot管理的版本:

查看SpringBoot管理版本

1
2
3
4
5
<properties>
<java.version>1.8</java.version>
<!-- 指定es版本为7.4.2,否则以spring-boot-starter-parent中为准,与自定义的冲突 -->
<elasticsearch.version>7.4.2</elasticsearch.version>
</properties>

3.启动报错

报错信息:Error creating bean with name ‘configurationPropertiesBeans’

1
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'configurationPropertiesBeans' defined in class path resource [org/springframework/cloud/autoconfigure/ConfigurationPropertiesRebinderAutoConfiguration.class]: Post-processing of merged bean definition failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [org.springframework.cloud.context.properties.ConfigurationPropertiesBeans] from ClassLoader [sun.misc.Launcher$AppClassLoader@18b4aac2]

报错原因:common中的alibaba-spring-cloud-nacos-discover,alibaba-spring-cloud-nacos-config两个依赖中的内部两个依赖:spring-cloud-commonsspring-cloud-context的版本,和spring-cloud-starter的内部两个依赖版本不同。
其他依赖common的微服务没有问题,是因为又引入了loader-balance之类的,其内部也有这两个依赖,覆盖之后就没有问题了。
所以我们手动引入这两个依赖,覆盖即可。引入依赖和spring-cloud-starter内部版本一致即可。

common微服务版本不一致问题

手动覆盖版本,与spring-cloud-starter保持一致

1
2
3
4
5
6
7
8
9
10
11
12
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-context -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>3.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-commons -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<version>3.1.2</version>
</dependency>

4.完整pom

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?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.6.8</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example.mall</groupId>
<artifactId>mall-search</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mall-search</name>
<description>mall检索服务</description>
<properties>
<java.version>1.8</java.version>
<!-- 指定es版本为7.4.2,否则以spring-boot-starter-parent中为准,与自定义的冲突 -->
<elasticsearch.version>7.4.2</elasticsearch.version>
</properties>
<dependencies>
<dependency>
<groupId>com.example.mall</groupId>
<artifactId>mall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<!-- common包中nacos下的cloud-context与cloud-commons 与 spring-cloud中的版本不一致,手动指定与spring一致的版本-->
<!--其他服务不报错的原因是因为引入了loadbalancer 或者feign,这中的覆盖了 -->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-context -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>3.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-commons -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<version>3.1.2</version>
</dependency>

<!-- es依赖 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.2</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

5.配置bootstrap文件

1
2
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.application.name=mall-search

6.编写ES配置文件

建立config包。于config包下创建ElasticSearchConfig类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* es配置类
* 1. 导入依赖
* 2. 编写配置,给容器注入一个RestHighLevelClient
*/
@Configuration
public class ElasticSearchConfig {

// ES通用配置,是公用的
public static final RequestOptions COMMON_OPTIONS;

static {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
COMMON_OPTIONS = builder.build();
}

// 将ES实例注入到IOC容器,后续都注入此实例使用即可
@Bean
public RestHighLevelClient esRestClient() {
return new RestHighLevelClient(
RestClient.builder(new HttpHost("127.0.0.1", 9200, "http"))
);
}
}

7. 测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
@SpringBootTest
class ElaTests {

@Autowired
private RestHighLevelClient client;

/**
* 存储测试用例
*/
@SneakyThrows
@Test
void indexData() {
// 获取users 索引(数据库)。如果没有会创建
IndexRequest indexRequest = new IndexRequest("users");
// id为1
indexRequest.id("1");
// indexRequest.source("userName", "zhangsan", "age", 18, "gender", "男");
User user = new User("zhangsan", "男", 18);
// 通过json存储
String s = JSONObject.toJSONString(user);
indexRequest.source(s, XContentType.JSON);

// 执行操作
IndexResponse index = client.index(indexRequest, ElasticSearchConfig.COMMON_OPTIONS);
System.out.println(index);
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class User {
private String userName;
private String gender;
private Integer age;
}

/**
* 查询
*/
@SneakyThrows
@Test
void searchData() {
// 1.创建检索请求
SearchRequest searchRequest = new SearchRequest();
// 2.指定索引
searchRequest.indices("bank");
// 3.指定检索条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 3.1 构造条件,对应具体的es的json中的语句
//sourceBuilder.query();
//sourceBuilder.from()
//sourceBuilder.size();
sourceBuilder.query(QueryBuilders.matchQuery("address", "mill"));
// 3.2按照年龄的值分布聚合
TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").size(10);
sourceBuilder.aggregation(ageAgg);
// 3.3计算平均值
searchRequest.source(sourceBuilder);
AvgAggregationBuilder balanceAvg = AggregationBuilders.avg("balanceAvg").field("balance");
sourceBuilder.aggregation(balanceAvg);
System.out.println(sourceBuilder.toString());

// 4.执行检索
SearchResponse search = client.search(searchRequest, ElasticSearchConfig.COMMON_OPTIONS);

// 5.分析结果
System.out.println(search.toString());
// 5.1获取查到的数据
SearchHits hits = search.getHits();
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
// 命中的记录信息
String sourceAsString = hit.getSourceAsString();
Account account = JSONObject.parseObject(sourceAsString, Account.class);
System.out.println("account: " + account);
}
// 5.2获取检索的分析信息
Aggregations aggregations = search.getAggregations();
Terms ageAgg1 = aggregations.get("ageAgg");
for (Terms.Bucket bucket : ageAgg1.getBuckets()) {
System.out.println("年龄:" + bucket.getKeyAsString() + " 总数" + bucket.getDocCount());
}

Avg balanceAvg1 = aggregations.get("balanceAvg");
System.out.println("平均薪资:" + balanceAvg1.getValueAsString());
}

/**
*
* (1)、冗余保存,方便检索
* {
* b:1
* skuTittle:离散数学及其应用
* price:128
* saleCount:99
* attrs:[
* {页数:500页}
* {作者:肯尼斯.H.罗森}
* ]
* }
* (2):节省了空间,但是拿spu查询的时候,回携带非常多的spuId,消耗过多的请求带宽,网络阻塞IO
* sku索引 {
* bId:1
* attrId:11
* xxxx
* }
* attr索引{
* attrId:11
* attrs:[
* {作者:肯尼斯.H.罗森}
* ]
* }
*/

@Test
void contextLoads() {
System.out.println(client);
}

}