SpringBoot整合ElasticSearch

1、导入依赖

这里的版本要和所按照的ELK版本匹配。

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

在spring-boot-dependencies中所依赖的ELK版本位6.8.7

1
<elasticsearch.version>6.8.7</elasticsearch.version>

image-20200511074437763

如果你使用Maven进行一个直接或间接继承spring-boot-dependencies(比如spring-boot-starter-parent)的构建,并想覆盖一个特定的第三方依赖,那你可以添加合适的元素。浏览spring-boot-dependencies POM可以获取一个全面的属性列表。例如,想要选择一个不同的elasticsearch版本,你可以添加以下内容将它改为7.6.2:

1
2
3
4
<properties>
...
<elasticsearch.version>7.6.2</elasticsearch.version>
</properties>

但是这只在你的Maven项目继承(直接或间接)自spring-boot-dependencies才有用。

如果你使用<scope>import</scope>,将spring-boot-dependencies添加到自己的dependencyManagement片段,那你必须自己重新定义artifact而不是覆盖属性。

image.png

需要在 <dependencyManagement> 下重新定义 artifact

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>

2、编写测试类

官方文档

1)测试保存数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
public void indexData() throws IOException {
IndexRequest indexRequest = new IndexRequest ("users");

User user = new User();
user.setUserName("张三");
user.setAge(20);
user.setGender("男");
String jsonString = JSON.toJSONString(user);
//设置要保存的内容
indexRequest.source(jsonString, XContentType.JSON);
//执行创建索引和保存数据
IndexResponse index = client.index(indexRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);

System.out.println(index);

}

测试前:

image-20200511111618183

测试后:

image-20200511112025327

2)测试获取数据

https://raw.githubusercontent.com/elastic/elasticsearch/master/docs/src/test/resources/accounts.json(官方数据样本)

查询state=”AK”的文档:

1
2
3
4
5
6
7
8
GET /bank/_search
{
"query": {
"match": {
"state.keyword": "AK"
}
}
}

java 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
void searchState() throws IOException {
// 创建检索条件
SearchRequest searchRequest = new SearchRequest();
//制定索引
searchRequest.indices("bank");
//指定DSL
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//构造检索条件
searchSourceBuilder.query(QueryBuilders.matchQuery("state.keyword", "AK"));

searchRequest.source(searchSourceBuilder);

SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(search.toString());

}

搜索address中包含mill的所有人的年龄分布以及平均年龄,平均薪资

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
GET bank/_search
{
"query": {
"match": {
"address": "Mill"
}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 10
}
},
"ageAvg": {
"avg": {
"field": "age"
}
},
"balanceAvg": {
"avg": {
"field": "balance"
}
}
}
}

java实现

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
/**
* 复杂检索:在bank中搜索address中包含mill的所有人的年龄分布以及平均年龄,平均薪资
* @throws IOException
*/
@Test
public void searchData() throws IOException {
//1. 创建检索请求
SearchRequest searchRequest = new SearchRequest();

//1.1)指定索引
searchRequest.indices("bank");
//1.2)构造检索条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchQuery("address","Mill"));

//1.2.1)按照年龄分布进行聚合
TermsAggregationBuilder ageAgg=AggregationBuilders.terms("ageAgg").field("age").size(10);
sourceBuilder.aggregation(ageAgg);

//1.2.2)计算平均年龄
AvgAggregationBuilder ageAvg = AggregationBuilders.avg("ageAvg").field("age");
sourceBuilder.aggregation(ageAvg);
//1.2.3)计算平均薪资
AvgAggregationBuilder balanceAvg = AggregationBuilders.avg("balanceAvg").field("balance");
sourceBuilder.aggregation(balanceAvg);

System.out.println("检索条件:"+sourceBuilder);
searchRequest.source(sourceBuilder);
//2. 执行检索
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("检索结果:"+searchResponse);

//3. 将检索结果封装为Bean
SearchHits hits = searchResponse.getHits();
SearchHit[] searchHits = hits.getHits();
for (SearchHit searchHit : searchHits) {
String sourceAsString = searchHit.getSourceAsString();
Account account = JSON.parseObject(sourceAsString, Account.class);
System.out.println(account);

}

//4. 获取聚合信息
Aggregations aggregations = searchResponse.getAggregations();

Terms ageAgg1 = aggregations.get("ageAgg");

for (Terms.Bucket bucket : ageAgg1.getBuckets()) {
String keyAsString = bucket.getKeyAsString();
System.out.println("年龄:"+keyAsString+" ==> "+bucket.getDocCount());
}
Avg ageAvg1 = aggregations.get("ageAvg");
System.out.println("平均年龄:"+ageAvg1.getValue());

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


}

可以尝试对比打印的条件和执行结果,和前面的ElasticSearch的检索语句和检索结果进行比较;