【ElasticSearch(十三)進階】SpringBoot整合ElasticSearch7.14.0 基本教程
一、接入方式
1.端口9300:TCP
1)spring-data-elasticsearch:transport-api.jar:
springboot版本不同,transport-api.jar 不同,不能適配es版本
7.x 已經不建議使用,8以后就要廢棄
2.端口9200:HTTP
1)JestClient
非官方,更新慢
2)RestTemplate
模擬發HTTP請求,ES很多操作需要自己封裝,麻煩
3)HttpClient
同上
4)Elasticsearch-Rest-Client(我們選擇的)
官方RestClient,封裝了ES操作,API層次分明,上手簡單
(使用指南)
https://www.elastic.co/guide/en/elasticsearch/client/index.html
二、搭建項目
我使用的版本是ElasticSearch 7.14,配合SpringBoot搭建項目。
三、導入Maven
由於父依賴spring-boot-dependencies
導入的elasticsearch
依賴版本是7.12.1
的,所以這里我們另外在<properties>
標簽下定義下elasticsearch
版本是7.14
的。
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.14.0</elasticsearch.version>
</properties>
<dependencies>
<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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- 導入es的rest-high-level-client和elasticsearch server-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.14.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.14.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
四、建立Config
建立config文件夾,創建類ElasticSearchConfig ,作為我們的配置文件。
給容器中注入一個RestHighLevelClient
package com.musecho.gulimallsearch.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ElasticSearchConfig {
/**
* 創建單例模式的RequestOptions,使得所有請求共用
*/
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();
}
@Bean
public RestHighLevelClient client() {
RestClientBuilder builder=RestClient.builder(new HttpHost("localhost", 9200, "http"));
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
}
五、測試:保存數據
保存一個user信息,使用index()
package com.musecho.gulimallsearch;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.musecho.gulimallsearch.config.ElasticSearchConfig;
import com.musecho.gulimallsearch.pojo.User;
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.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
@SpringBootTest
public class GulimallSearchApplicationTests {
@Autowired
private RestHighLevelClient client;
/**
* jackson的objectMapper
*/
ObjectMapper objectMapper=new ObjectMapper();
/**
* 測試RestHighLevelClient注入是否成功
*/
@Test
public void contextLoads() {
System.out.println(client);
}
/**
* 保存用戶數據
*/
@Test
public void indexData() throws IOException {
//指定索引和id
IndexRequest request=new IndexRequest("users");
request.id("1");
//數據轉為json格式
User user=new User("zhengkeke","女",9);
String userString=objectMapper.writeValueAsString(user);
request.source(userString, XContentType.JSON);
//執行保存操作
IndexResponse indexResponse=client.index(request, ElasticSearchConfig.COMMON_OPTIONS);
System.out.println(indexResponse);
}
}
通過Kinaba查詢是否添加成功:
GET /users/_search
返回結果如下, 保存數據成功
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "users",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name" : "zhengkeke",
"sex" : "女",
"age" : 9
}
}
]
}
}
六、測試:復雜檢索數據
現在用java結合ES實現這個查詢
#搜索 address中包含mill的所有人的年齡分布以及平均年齡
GET /bank/_search
{
"query":{
"match":{
"address":"mill"
}
},
"aggs":{
"ageAgg":{
"terms":{
"field": "age",
"size": 10
}
},
"ageAvg":{
"avg":{
"field":"age"
}
}
}
}
類GulimallSearchApplicationTests中添加方法searchData()
/**
* 復雜檢索數據
*/
@Test
public void searchData() throws IOException {
//1.創建檢索請求
SearchRequest searchRequest = new SearchRequest();
//指定索引
searchRequest.indices("bank");
//指定DSL,檢索條件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//1.1 構造檢索條件
//address中包含mill
searchSourceBuilder.query(QueryBuilders.matchQuery("address", "mill"));
//按照前10種年齡分布進行聚合
TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").size(10);
searchSourceBuilder.aggregation(ageAgg);
//求所有人年齡的平均值
AvgAggregationBuilder ageAvg = AggregationBuilders.avg("ageAvg").field("age");
searchSourceBuilder.aggregation(ageAvg);
System.out.println(searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
//2.執行檢索
SearchResponse searchResponse = client.search(searchRequest, ElasticSearchConfig.COMMON_OPTIONS);
//3.分析結果
//3.1 查看查詢結果
SearchHits hits = searchResponse.getHits();
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
System.out.println(hit);
}
//3.2 查看聚合結果
Aggregations aggs = searchResponse.getAggregations();
Terms ageAgg2 = aggs.get("ageAgg");
for (Terms.Bucket bucket : ageAgg2.getBuckets()) {
System.out.println("年齡:" + bucket.getKeyAsString()+"==> 人數:"+bucket.getDocCount());
}
System.out.println();
Avg ageAvg2 = aggs.get("ageAvg");
System.out.println("平均年齡:" + ageAvg2.getValue());
}
控制台打印結果:
//請求條件
{
"query": {
"match": {
"address": {
"query": "mill",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1
}
}
},
"aggregations": {
"ageAgg": {
"terms": {
"field": "age",
"size": 10,
"min_doc_count": 1,
"shard_min_doc_count": 0,
"show_term_doc_count_error": false,
"order": [
{
"_count": "desc"
},
{
"_key": "asc"
}
]
}
},
"ageAvg": {
"avg": {
"field": "age"
}
}
}
}
//查詢結果
{
"_index" : "bank",
"_type" : "account",
"_id" : "970",
"_score" : 5.4032025,
"_source" : {
"account_number" : 970,
"balance" : 19648,
"firstname" : "Forbes",
"lastname" : "Wallace",
"age" : 28,
"gender" : "M",
"address" : "990 Mill Road",
"employer" : "Pheast",
"email" : "forbeswallace@pheast.com",
"city" : "Lopezo",
"state" : "AK"
}
}
{
"_index" : "bank",
"_type" : "account",
"_id" : "136",
"_score" : 5.4032025,
"_source" : {
"account_number" : 136,
"balance" : 45801,
"firstname" : "Winnie",
"lastname" : "Holland",
"age" : 38,
"gender" : "M",
"address" : "198 Mill Lane",
"employer" : "Neteria",
"email" : "winnieholland@neteria.com",
"city" : "Urie",
"state" : "IL"
}
}
{
"_index" : "bank",
"_type" : "account",
"_id" : "345",
"_score" : 5.4032025,
"_source" : {
"account_number" : 345,
"balance" : 9812,
"firstname" : "Parker",
"lastname" : "Hines",
"age" : 38,
"gender" : "M",
"address" : "715 Mill Avenue",
"employer" : "Baluba",
"email" : "parkerhines@baluba.com",
"city" : "Blackgum",
"state" : "KY"
}
}
{
"_index" : "bank",
"_type" : "account",
"_id" : "472",
"_score" : 5.4032025,
"_source" : {
"account_number" : 472,
"balance" : 25571,
"firstname" : "Lee",
"lastname" : "Long",
"age" : 32,
"gender" : "F",
"address" : "288 Mill Street",
"employer" : "Comverges",
"email" : "leelong@comverges.com",
"city" : "Movico",
"state" : "MT"
}
}
//聚合結果
年齡:38==> 人數:2
年齡:28==> 人數:1
年齡:32==> 人數:1
平均年齡:34.0