目錄
- 1. 引入依賴
- 2. 添加組態檔
- 3. 創建ES配置類
- 4. swagger配置類
- 5. 訊息回傳體
- 6. 創建保存檔案的物體
- 7. 索引操作service
- 8. 創建索引controller
- 9. 測驗索引操作
- 9.1 創建索引
- 9.2 判斷索引是否存在
- 9.3 洗掉索引
- 10. 檔案操作service
- 11. 創建檔案controller
- 12. 測驗檔案操作
- 12.1 插入檔案
- 12.2 查詢檔案
- 12.3 更新檔案
- 12.4 洗掉檔案
- 13. search操作service
- 14. search操作controller
- 15. 測驗search介面操作
- 15.1 _search介面基本用法
- 15.2 基于詞項的查詢
- 15.3 基于全文的查詢
- 15.4 基于全文的模糊查詢
- 15.5 組合查詢
- 16. 聚集操作service
- 17. 聚集查詢controller
- 18. 測驗聚集查詢
- 代碼下載地址
1. 引入依賴
- 這里使用springboot 2.5.4 版本,es使用 7.14.0 版本
- 可以參考es 官方檔案 ,在Java REST Client 下找到對應的版本

- 這里使用7.14.0的 Java High Level REST Client

- 右下角有詳細的使用說明

- 需要同時使用elasticsearch和elasticsearch-rest-high-level-client

<?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.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>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>
<!-- es-->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.14.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.14.0</version>
</dependency>
<!-- fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.57</version>
</dependency>
<!-- Swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</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>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
2. 添加組態檔
#es
elasticsearch.host=192.168.42.111
elasticsearch.port=9200
#jackson
spring.jackson.default-property-inclusion=non_null
3. 創建ES配置類
package com.example.demo.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ESConfig {
@Value("${elasticsearch.host}")
private String host;
@Value("${elasticsearch.port}")
private int port;
@Bean
public RestHighLevelClient highLevelClient() {
HttpHost httpHost = new HttpHost(host, port, "http");
// 如果是集群模式,可以添加HttpHost陣列
RestClientBuilder restClientBuilder = RestClient.builder(httpHost);
return new RestHighLevelClient(restClientBuilder);
}
}
4. swagger配置類
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
.apis(RequestHandlerSelectors.basePackage("com.example.demo")).build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().version("1.0").build();
}
}
5. 訊息回傳體
- 用來包裝回傳資料
package com.example.demo.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AjaxResult<T> {
private Integer code;
private String message;
private T data;
public static <T> AjaxResult<T> ok(T data) {
return new AjaxResult<>(0, "success", data);
}
public static <T> AjaxResult<T> error(T data) {
return new AjaxResult<>(1, "error", data);
}
}
6. 創建保存檔案的物體
package com.example.demo.vo;
import lombok.Data;
@Data
public class User {
private String firstName;
private String secondName;
private String content;
private Integer age;
}
7. 索引操作service
- 這里對索引進行創建,判斷索引是否存在和洗掉索引
package com.example.demo.service;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
@Service
public class OperateIndex {
@Resource
private RestHighLevelClient restHighLevelClient;
public boolean createIndex(String indexName) {
boolean acknowledged = false;
try {
/**
* 可以根據需要設定欄位屬性,如果不設定,es會根據添加檔案時的欄位型別自動推斷
* put /{indexName}/_mapping
* {
* "properties": {
* "firstName": {
* "type": "keyword"
* },
* "secondName": {
* "type": "keyword"
* },
* "age": {
* "type": "integer"
* },
* "content": {
* "type": "text"
* }
* }
* }
*/
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder()
.startObject()
.field("properties").startObject()
.field("firstName").startObject().field("type", "keyword").endObject()
.field("secondName").startObject().field("type", "keyword").endObject()
.field("age").startObject().field("type", "integer").endObject()
.field("content").startObject().field("type", "text").endObject()
.endObject()
.endObject();
CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
createIndexRequest.mapping(xContentBuilder);
CreateIndexResponse createIndexResponse =
restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
acknowledged = createIndexResponse.isAcknowledged();
} catch (IOException e) {
e.printStackTrace();
}
return acknowledged;
}
public boolean isIndexExists(String indexName) {
GetIndexRequest getIndexRequest = new GetIndexRequest(indexName);
getIndexRequest.humanReadable(true);
boolean exists = false;
try {
exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
return exists;
}
public boolean deleteIndex(String indexName) {
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName);
// 忽略索引不存在的情況;如果不設定,索引不存在時,會報錯
deleteIndexRequest.indicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN);
boolean acknowledged = false;
try {
AcknowledgedResponse delete =
restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
acknowledged = delete.isAcknowledged();
} catch (IOException e) {
e.printStackTrace();
}
return acknowledged;
}
}
8. 創建索引controller
package com.example.demo.controller;
import com.example.demo.service.OperateIndex;
import com.example.demo.vo.AjaxResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/index")
public class IndexController {
@Resource
private OperateIndex operateIndex;
/*
* 創建索引
*/
@PostMapping("/create")
public AjaxResult<Boolean> createIndex(@RequestParam String indexName) {
return AjaxResult.ok(operateIndex.createIndex(indexName));
}
/**
* 索引是否存在
*/
@PostMapping("/exit")
public AjaxResult<Boolean> indexExit(@RequestParam String indexName) {
return AjaxResult.ok(operateIndex.isIndexExists(indexName));
}
/**
* 洗掉索引
*/
@PostMapping("/delete")
public AjaxResult<Boolean> deleteIndex(@RequestParam String indexName) {
return AjaxResult.ok(operateIndex.deleteIndex(indexName));
}
}
9. 測驗索引操作
9.1 創建索引

- 查看是否創建成功

9.2 判斷索引是否存在

9.3 洗掉索引

- 再次查看索引是否存在

10. 檔案操作service
package com.example.demo.service;
import com.alibaba.fastjson.JSON;
import com.example.demo.vo.AjaxResult;
import com.example.demo.vo.User;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.get.GetResult;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Objects;
@Service
public class OperateDoc {
@Resource
private RestHighLevelClient restHighLevelClient;
public AjaxResult<String> insertDoc(User user, String indexName, String docId) {
IndexRequest indexRequest = new IndexRequest(indexName);
//設定檔案id,如果不設定id,es會自動生成全域唯一的id
indexRequest.id(docId);
//設定檔案資料和格式
indexRequest.source(JSON.toJSONString(user), XContentType.JSON);
try {
//獲取回傳的response
IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
if (Objects.nonNull(indexResponse)) {
String id = indexResponse.getId();
DocWriteResponse.Result result = indexResponse.getResult();
// 如果設定的id不存在,則新增檔案;如果id已存在,則覆寫檔案
if (Objects.equals(result, DocWriteResponse.Result.CREATED)) {
return new AjaxResult<>(0, "新增檔案成功!", id);
} else if (Objects.equals(result, DocWriteResponse.Result.UPDATED)) {
return new AjaxResult<>(0, "覆寫檔案成功!", id);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public AjaxResult<String> getDoc(String indexName, String docId) {
GetRequest getRequest = new GetRequest(indexName, docId);
try {
GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
if (getResponse.isExists()) {
return AjaxResult.ok(getResponse.getSourceAsString());
} else {
return AjaxResult.error("檔案不存在!");
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public AjaxResult<String> updateDoc(String indexName, String docId, String fieldName,String fieldValue) {
try {
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder();
xContentBuilder.startObject();
xContentBuilder.field(fieldName, fieldValue);
xContentBuilder.endObject();
UpdateRequest updateRequest = new UpdateRequest(indexName, docId);
updateRequest.doc(xContentBuilder);
//id不存在則添加檔案
updateRequest.docAsUpsert(true);
//在應答里包含當前檔案的內容
updateRequest.fetchSource(true);
UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
GetResult getResult = updateResponse.getGetResult();
if (getResult.isExists()) {
return AjaxResult.ok(getResult.sourceAsString());
} else {
return AjaxResult.error("更新檔案失敗!");
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public AjaxResult<String> deleteDoc(String indexName, String docId) {
DeleteRequest deleteRequest = new DeleteRequest(indexName, docId);
try {
DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
if (Objects.equals(deleteResponse.getResult(), DocWriteResponse.Result.DELETED)) {
return AjaxResult.ok("檔案洗掉成功!");
} else if (Objects.equals(deleteResponse.getResult(), DocWriteResponse.Result.NOT_FOUND)) {
return AjaxResult.error("檔案不存在");
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
11. 創建檔案controller
package com.example.demo.controller;
import com.example.demo.service.OperateDoc;
import com.example.demo.vo.AjaxResult;
import com.example.demo.vo.User;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/doc")
public class DocController {
@Resource
private OperateDoc operateDoc;
/**
* 插入檔案
*/
@PostMapping("/insert")
public AjaxResult<String> insertDoc(@RequestBody User user, @RequestParam String indexName,
@RequestParam String docId) {
return operateDoc.insertDoc(user, indexName, docId);
}
/**
* 查詢檔案
*/
@PostMapping("/query")
public AjaxResult<String> getDoc(@RequestParam String indexName, @RequestParam String docId) {
return operateDoc.getDoc(indexName, docId);
}
/**
* 更新檔案
*/
@PostMapping("/updata")
public AjaxResult<String> updateDoc(@RequestParam String indexName, @RequestParam String docId,
@RequestParam String fieldName, @RequestParam String fieldValue) {
return operateDoc.updateDoc(indexName, docId, fieldName, fieldValue);
}
/**
* 洗掉檔案
*/
@PostMapping("/delete")
public AjaxResult<String> deleteDoc(@RequestParam String indexName, @RequestParam String docId) {
return operateDoc.deleteDoc(indexName, docId);
}
}
12. 測驗檔案操作
12.1 插入檔案


12.2 查詢檔案

12.3 更新檔案


12.4 洗掉檔案


13. search操作service
package com.example.demo.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.vo.AjaxResult;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.FuzzyQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
@Service
public class NormalSearch {
@Resource
private RestHighLevelClient restHighLevelClient;
/**
* 處理回傳結果中的hits部分
*/
public AjaxResult<JSONArray> send(String indexName, SearchSourceBuilder searchSourceBuilder) {
try {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(indexName);
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = search.getHits();
JSONArray jsonArray = new JSONArray();
for (SearchHit hit : hits) {
String src = hit.getSourceAsString();
JSONObject jsonObject = JSON.parseObject(src);
jsonArray.add(jsonObject);
}
return AjaxResult.ok(jsonArray);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* _search介面基本用法
*/
public AjaxResult<JSONArray> searchExample(String indexName) {
/**
* 拼接查詢條件
* get kibana_sample_data_flights/_search
* {
* "from":0,
* "size":5,
* "query":{
* "match_all":{}
* },
* "_source":["Origin*","*Weather"],
* "sort":[{"DistanceKilometers":"asc"},{"FlightNum":"desc"}]
* }
*/
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.from(0);
searchSourceBuilder.size(5);
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
String[] includeFields = new String[]{"Origin*", "*Weather"};
searchSourceBuilder.fetchSource(includeFields, null);
searchSourceBuilder.sort(new FieldSortBuilder("DistanceKilometers").order(SortOrder.ASC));
searchSourceBuilder.sort(new FieldSortBuilder("FlightNum").order(SortOrder.DESC));
return send(indexName, searchSourceBuilder);
}
/**
* 基于詞項的查詢
*/
public AjaxResult<JSONArray> termsSearch(String indexName) {
/**
* get kibana_sample_data_flights/_search
* {
* "query":{
* "term":{
* "dayOfWeek":3
* }
* }
* }
*/
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("dayOfWeek", 3);
searchSourceBuilder.query(termQueryBuilder);
return send(indexName, searchSourceBuilder);
}
/**
* 基于全文的查詢
*/
public AjaxResult<JSONArray> matchSearch(String indexName) {
/**
* POST /kibana_sample_data_flights/_search
* {
* "query": {
* "multi_match": {
* "query":"AT",
* "fields":["DestCountry", "OriginCountry"]
* }
* }
* }
*/
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.multiMatchQuery("AT", "DestCountry", "OriginCountry"));
return send(indexName, searchSourceBuilder);
}
/**
* 基于全文的模糊查詢
*/
public AjaxResult<JSONArray> fuzzySearch(String indexName) {
/**
* get kibana_sample_data_logs/_search
* {
* "query": {
* "fuzzy": {
* "message": {
* "value": "firefix",
* "fuzziness": "1"
* }
* }
* }
* }
*/
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("message", "firefix");
fuzzyQueryBuilder.fuzziness(Fuzziness.ONE);
searchSourceBuilder.query(fuzzyQueryBuilder);
return send(indexName, searchSourceBuilder);
}
/**
* 組合查詢范例
*/
public AjaxResult<JSONArray> boolSearch(String indexName) {
/**
* POST /kibana_sample_data_logs/_search
* {
* "query": {
* "bool": {
* "must":[
* {"match": { "message": "firefox"} }
* ],
* "should":[
* {"term": { "geo. src": "CN"}},
* {"term": { "geo. dest": "CN"}}
* ]
* }
* }
* }
*/
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.matchQuery("message", "firefox"))
.should(QueryBuilders.termQuery("geo.src", "CN"))
.should(QueryBuilders.termQuery("geo.dest", "CN"));
searchSourceBuilder.query(boolQueryBuilder);
return send(indexName, searchSourceBuilder);
}
}
14. search操作controller
package com.example.demo.controller;
import com.alibaba.fastjson.JSONArray;
import com.example.demo.service.NormalSearch;
import com.example.demo.vo.AjaxResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/search")
public class SearchController {
private final static String KIBANA_SAMPLE_DATA_FLIGHTS = "kibana_sample_data_flights";
private final static String KIBANA_SAMPLE_DATA_LOGS = "kibana_sample_data_logs";
@Resource
private NormalSearch normalSearch;
/**
* _search介面基本用法
*/
@PostMapping("/example")
public AjaxResult<JSONArray> searchExample() {
return normalSearch.searchExample(KIBANA_SAMPLE_DATA_FLIGHTS);
}
/**
* 基于詞項的查詢
*/
@PostMapping("/term")
public AjaxResult<JSONArray> termsSearch() {
return normalSearch.termsSearch(KIBANA_SAMPLE_DATA_FLIGHTS);
}
/**
* 基于全文的查詢
*/
@PostMapping("/match")
public AjaxResult<JSONArray> matchSearch() {
return normalSearch.matchSearch(KIBANA_SAMPLE_DATA_FLIGHTS);
}
/**
* 基于全文的模糊查詢
*/
@PostMapping("/fuzzy")
public AjaxResult<JSONArray> fuzzySearch() {
return normalSearch.fuzzySearch(KIBANA_SAMPLE_DATA_LOGS);
}
/**
* 組合查詢范例
*/
@PostMapping("/combination")
public AjaxResult<JSONArray> combinationSearch() {
return normalSearch.boolSearch(KIBANA_SAMPLE_DATA_LOGS);
}
}
15. 測驗search介面操作
- 測驗之前需要提前匯入es提供的樣例資料kibana_sample_data_flights和kibana_sample_data_logs,參考資料檢索和分析
15.1 _search介面基本用法

15.2 基于詞項的查詢

15.3 基于全文的查詢

15.4 基于全文的模糊查詢

15.5 組合查詢

16. 聚集操作service
package com.example.demo.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.vo.AjaxResult;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
import org.elasticsearch.search.aggregations.metrics.ParsedAvg;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
@Service
public class AggsSearch {
@Resource
private RestHighLevelClient restHighLevelClient;
/**
* 處理回傳結果中的hits和聚集
*/
public AjaxResult<JSONArray> send(String indexName, SearchSourceBuilder searchSourceBuilder) {
try {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(indexName);
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = search.getHits();
JSONArray jsonArray = new JSONArray();
//hits部分
for (SearchHit hit : hits) {
String src = hit.getSourceAsString();
JSONObject jsonObject = JSON.parseObject(src);
jsonArray.add(jsonObject);
}
//聚集部分
Aggregations aggregations = search.getAggregations();
for (Aggregation aggregation : aggregations) {
String jsonString = JSON.toJSONString(aggregation);
jsonArray.add(JSON.parseObject(jsonString));
//這里可以拿到具體的桶聚集,做特殊處理
List<? extends Histogram.Bucket> buckets = ((Histogram) aggregation).getBuckets();
for (Histogram.Bucket bucket : buckets) {
System.out.println("--------------------------------------");
System.out.println(bucket.getKeyAsString());
System.out.println(bucket.getDocCount());
ParsedAvg parsedAvg = (ParsedAvg) bucket.getAggregations().getAsMap().get("avg_price");
System.out.println(parsedAvg.getValueAsString());
}
}
return AjaxResult.ok(jsonArray);
} catch (IOException e) {
e.printStackTrace();
}
return AjaxResult.error(null);
}
/**
* 聚集查詢
*/
public AjaxResult aggsExampleSearch(String indexName) {
/**
* high level client不能使用過濾條件filter_path,如果要使用,只能使用low level client
* POST /kibana_sample_data_flights/_search?filter_path=aggregations
* {
* "query": {
* "term": {"OriginCountry": "CN"}
* },
* "aggs":
* {
* "date_price_histogram": {
* "date_histogram": {
* "field": "timestamp",
* "fixed_interval": "30d"
* },
* "aggs": {
* "avg_price": {"avg": {"field": "FlightDelayMin"}}
* }
* }
* }
* }
*/
// 拼接query部分
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.termQuery("OriginCountry", "CN"));
//拼接聚集部分
DateHistogramAggregationBuilder date_price_histogram
= AggregationBuilders.dateHistogram("date_price_histogram");
date_price_histogram.field("timestamp").fixedInterval(DateHistogramInterval.days(30));
//嵌套聚集部分
date_price_histogram.subAggregation(AggregationBuilders.avg("avg_price").field("FlightDelayMin"));
searchSourceBuilder.aggregation(date_price_histogram);
return send(indexName, searchSourceBuilder);
}
}
17. 聚集查詢controller
package com.example.demo.controller;
import com.alibaba.fastjson.JSONArray;
import com.example.demo.service.AggsSearch;
import com.example.demo.vo.AjaxResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/aggs")
public class AggsController {
private final static String KIBANA_SAMPLE_DATA_FLIGHTS = "kibana_sample_data_flights";
@Resource
private AggsSearch aggsSearch;
/**
* 聚集查詢
*/
@PostMapping("/query")
public AjaxResult<JSONArray> aggsQuery() {
return aggsSearch.aggsExampleSearch(KIBANA_SAMPLE_DATA_FLIGHTS);
}
}
18. 測驗聚集查詢
- 直接使用kibana查詢的結果

- 介面呼叫結果

- 控制臺列印

代碼下載地址
https://gitee.com/fisher3652/es_demo
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/438081.html
標籤:其他
