版权说明: 本文由博主keep丶原创,转载请注明出处。
原文地址: https://blog.csdn.net/qq_38688267/article/details/120283675
文章目录
准备工作
依赖
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.10.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.10.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.10.2</version>
</dependency>
配置
属性类
/**
* ES参数
*/
@Data
@ConfigurationProperties(prefix = "map.es")
public class EsProperties {
/**
* 地址
*/
private String host;
/**
* 端口
*/
private Integer port;
/**
* 协议
*/
private String scheme;
/**
* 端口
*/
private String username;
/**
* 协议
*/
private String password;
}
配置类
/**
* ES配置类
*/
@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(EsProperties.class)
public class EsConfig {
private final EsProperties properties;
@Bean
@SneakyThrows
public RestHighLevelClient startRestClient() {
BasicCredentialsProvider basicCredentialsProvider = new BasicCredentialsProvider();
// 登录认证
basicCredentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(properties.getUsername(), properties.getPassword()));
// https连接需要增加以下配置
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (arg0, arg1) -> true).build();
RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(properties.getHost(), properties.getPort(), properties.getScheme()))
.setHttpClientConfigCallback(httpAsyncClientBuilder -> {
httpAsyncClientBuilder.disableAuthCaching();
httpAsyncClientBuilder.setSSLContext(sslContext);
httpAsyncClientBuilder.setSSLHostnameVerifier((s, sslSession) -> true);
return httpAsyncClientBuilder.setDefaultCredentialsProvider(basicCredentialsProvider);
});
return new RestHighLevelClient(restClientBuilder);
}
}
实战前言
请求结构介绍
在进行实战之前,我们先来学习一下ES的API请求及其响应的结构。以下展示的是ES自带的请求工具的信息,JAVA请求实际也是通过代码实现这些对象的构建。
请求体
响应体
代码逻辑介绍
大的代码逻辑如下,几个核心对象是SearchRequest
,SearchSource
,Query
,Aggregation
,,SearchResponse
,Hits
等。
ES官方提供的API多是以建造者模式实现对象创建,核心工具类是QueryBuilders
和各种xxxBuilders
。
// 创建请求
SearchRequest searchRequest = new SearchRequest();
// 设置索引
request.indices(IDX);
// 创建查询构造器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 设置查询详情返回条数,如果不传则默认使用服务端的值
searchSourceBuilder.size(10);
// 全值匹配
QueryBuilder fullMatchQuery = QueryBuilders.termQuery(field, param);
// 将条件注入到查询中
searchSourceBuilder.query(fullMatchQuery);
// 定义聚合操作
AggregationBuilder appNumBuilder = AggregationBuilders.cardinality("fieldResultName").field("fieldName.keyword");
// 将聚合操作注入到请求中
searchSourceBuilder.aggregation(appNumBuilder);
// 将查询体注入到请求中
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse;
try {
// 发送请求
searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
}
} catch (IOException e) {
e.printStackTrace();
}
// 拿到总数
SearchHits searchhits = searchResponse.getHits();
long totalCount = searchhits.getTotalHits().value;
meta.setTotalCount(totalCount);
// 遍历查询内容
for (SearchHit searchHit : searchhits) {
// ...
}
// 获取聚合操作返回值
ParsedCardinality appResult = response.getAggregations().get("fieldResultName");
long appNum = appResult.getValue();
需求实战
普通查询
全值匹配
QueryBuilders.termQuery("fieldName", "param");
请求体:
{
"query":{
"term":{
"fieldName":{
"value":"param"
}
}
}
}
模糊查询
// .keyword表示不分词
// * 号必须手动加,API本身不会加,因此要全模糊就左右拼"*"号。
QueryBuilders.wildcardQuery("fieldName", "*param*");
请求体:
{
"query":{
"wildcard":{
"fieldName.keyword":{
"value":"*param*"
}
}
}
}
范围查询
// 参数可以为时间、数字等,需要与字段类型一致
QueryBuilders.rangeQuery("fieldName")
// 大于等于, gt 大于
.gte(1)
// 小于等于, lt 小于
.lte(100);
请求体:
{
"query":{
"range":{
"fieldName":{
"gte":1,
"lte":100
}
}
}
}
聚合查询
根据一个字段分组统计
// 如果不需要返回数据详情,则设置size为0,规避不必要的消耗。
searchRequest.size(0);
AggregationBuilders.terms("resultFieldName")
.field("fieldName.keyword");
请求体:
{
"size": 0,
"query":{
"aggregations":{
"resultFieldName":{
"terms":{
"field":"fieldName.keyword"
}
}
}
}
}
根据时间分组统计
// 如果不需要返回数据详情,则设置size为0,规避不必要的消耗。
DateHistogramAggregationBuilder aggregationBuilder = AggregationBuilders
.dateHistogram("resultFieldName")
.field("fieldName")
// 按天统计
.calendarInterval(DateHistogramInterval.DAY);
请求体:
GET _search
{
"size": 0,
"aggregations":{
"StartUTC_groupby":{
"date_histogram":{
"field":"traefik.time",
"calendar_interval":"1d"
}
}
}
}
calendar_interval
取值介绍:
值 | 含义 |
---|---|
1y | 年 |
1q | 季 |
1M | 月 |
1w | 周 |
1d | 日 |
1h | 时 |
1m | 分 |
1s | 秒 |
多字段统计
// 如果不需要返回数据详情,则设置size为0,规避不必要的消耗。
DateHistogramAggregationBuilder aggregationBuilder = AggregationBuilders
.dateHistogram("resultFieldName")
.field("fieldName")
// 按天统计
.calendarInterval(DateHistogramInterval.DAY);
// 添加子聚合对象
//最大值
aggregationBuilder.subAggregation(AggregationBuilders.max("maxResultFieldName").field("fieldName"));
//最小值
aggregationBuilder.subAggregation(AggregationBuilders.max("minResultFieldName").field("fieldName"));
//平均值
aggregationBuilder.subAggregation(AggregationBuilders.avg("avgResultFieldName").field("fieldName"));
//失败响应次数, 添加一个范围统计字段
aggregationBuilder.subAggregation(
AggregationBuilders.range("failRequestResultName")
.addRange(HttpStatus.HTTP_BAD_REQUEST, HttpStatus.HTTP_VERSION)
.field("fieldName2")
);
请求体:
GET _search
{
"size": 0,
"aggregations":{
"StartUTC_groupby":{
"date_histogram":{
"field":"traefik.time",
"calendar_interval":"1d"
},
"aggregations":{
"maxResultFieldName":{
"max":{
"field":"fieldName"
}
},
"minResultFieldName":{
"min":{
"field":"fieldName"
}
},
"avgResultFieldName":{
"avg":{
"field":"fieldName"
}
},
"failRequestResultName":{
"range":{
"field":"fieldName2",
"ranges":[
{
"from":400,
"to":505
}
],
"keyed":false
}
}
}
}
}
}
补充
灵活利用DEBUG调试
在实际编码过程中,难免会碰到各种问题,此时我们可以在request.source(sourceBuilder);
代码之后打个断点,查看searchRequest
中的查询信息,如下图,并复制source
属性的值,将该值直接复制到ES提供的工具中执行查看效果,并调试。
在获取返回值的时候亦然,如果不清楚该如何获取返回值,则打个断点,先查看response
的结构,在根据结构一个个将需要的数据获取出来。
封装代码
字段名封装
一定要封装代码,虽然ES提供的API已经很多了,但是结合需求,还是有很多可以封装的,比如字段值,文中这种直接传"fieldName"
的方式是非常不可取的,我们要专门用一个类来声明维护,同时可能还需要声明不分词还需要拼接.keyword
后缀,还需要定义返回值列名等,作者是直接将这些字段封装成一个ENUM
枚举类:
@AllArgsConstructor
public enum EsFieldEnum {
/**
* 应用名
*/
REQUEST_HOST("RequestHost"),
/**
* uri
*/
REQUEST_PATH("RequestPath"),
/**
* 响应码
*/
ORIGIN_STATUS("OriginStatus"),
/**
* 调用方IP
*/
CLIENT_ADDR("ClientAddr");
private final String name;
// 字段名前缀
private static final String NAME_PREFIX = "traefik.";
// 关键词后缀
private static final String KEY_WORD_SUFFIX = ".keyword";
// 分组字段名统一后缀
private static final String GROUP_BY_SUFFIX = "_groupby";
// 分组字段名统一后缀
private static final String MAX_SUFFIX = "_max";
// 分组字段名统一后缀
private static final String MIN_SUFFIX = "_min";
// 分组字段名统一后缀
private static final String AVG_SUFFIX = "_avg";
// 统计字段名统一后缀
private static final String COUNT_SUFFIX = "_count";
/**
* 获取该字段值
*/
public String getName() {
return NAME_PREFIX + name;
}
/**
* 获取该字段对应的关键词字段名
*/
public String keyword() {
return NAME_PREFIX + name + KEY_WORD_SUFFIX;
}
/* **********以下为字段别名********** */
/**
* 获取该字段对应的分组字段名
*/
public String groupBy() {
return name + GROUP_BY_SUFFIX;
}
/**
* 获取该字段对应的分组字段名
*/
public String max() {
return name + MAX_SUFFIX;
}
/**
* 获取该字段对应的分组字段名
*/
public String min() {
return name + MIN_SUFFIX;
}
/**
* 获取该字段对应的分组字段名
*/
public String avg() {
return name + AVG_SUFFIX;
}
/**
* 获取该字段对应的统计字段名
*/
public String count() {
return name + COUNT_SUFFIX;
}
这样在使用的时候就非常方便:
工具类封装
为了提高代码复用率,作者封装了基于自身需求的工具类,提高代码复用率。这里抛砖引玉,希望能给大家带来一些启发:
/**
* ES操作辅助类
*
* @author zzf
* @date 2021年9月9日09:14:00
*/
public class EsHelper {
private static final String IDX = "traefik-*";
/**
* 新建一个固定索引的SearchRequest
* *****************注意********************
* 此方法创建的请求没有指定固定的索引,因此需要使用{@link #newSearchBuilder(Date, Date)}方法创建包含时间区间条件的builder
*
* @return 一个指定索引的SearchRequest
*/
public static SearchRequest newRequest() {
SearchRequest request = new SearchRequest();
request.indices(IDX);
return request;
}
/**
* 新建一个包含请求时间条件的Builder
*
* @param startTime 开始时间
* @param endTime 结束时间
*/
public static SearchSourceBuilder newSearchBuilder(Date startTime, Date endTime) {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(
new RangeQueryBuilder(EsFieldEnum.START_UTC.getName())
.gte(startTime)
.lte(endTime)
);
searchSourceBuilder.size(0);
return searchSourceBuilder;
}
/**
* 新建一个包含请求时间条件的Builder
*
* @param startTime 开始时间
* @param endTime 结束时间
*/
public static SearchSourceBuilder newAggSearchBuilder(Date startTime, Date endTime) {
SearchSourceBuilder searchSourceBuilder = newAggSearchBuilder();
searchSourceBuilder.query(
new RangeQueryBuilder(EsFieldEnum.START_UTC.getName())
.gte(startTime)
.lte(endTime)
);
return searchSourceBuilder;
}
public static SearchSourceBuilder newAggSearchBuilder() {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.size(0);
return searchSourceBuilder;
}
/**
* 新建一个包含请求时间条件的Builder
*
* @param startTime 开始时间
* @param endTime 结束时间
*/
public static QueryBuilder newRangeQuery(Date startTime, Date endTime) {
return new RangeQueryBuilder(EsFieldEnum.START_UTC.getName())
.gte(startTime)
.lte(endTime);
}
/**
* 新建包含请求时间条件并与传入条件为取并集(and &)的Builder
*
* @param otherCondition 另外一个条件builder
* @param startTime 开始时间
* @param endTime 结束时间
*/
public static QueryBuilder newMustQuery(QueryBuilder otherCondition, Date startTime, Date endTime) {
return QueryBuilders.boolQuery()
.must(otherCondition)
.must(QueryBuilders.rangeQuery(EsFieldEnum.START_UTC.getName()).gte(startTime).lte(endTime));
}
/**
* 新建包含请求时间条件的条件Builder
*
* @param startTime 开始时间
* @param endTime 结束时间
*/
public static BoolQueryBuilder newBoolQuery(Date startTime, Date endTime) {
return QueryBuilders.boolQuery()
.must(QueryBuilders.rangeQuery(EsFieldEnum.START_UTC.getName()).gte(startTime).lte(endTime));
}
/**
* 新建一个包含分页的Builder
*
* @param from
* @param size
*/
public static SearchSourceBuilder newPageBuilder(Integer from, Integer size) {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.from(from);
searchSourceBuilder.size(size);
return searchSourceBuilder;
}
/**
* 新建一个根据指定字段统计的聚合builder
*
* @param fieldEnum 字段枚举值
*/
public static AggregationBuilder newCountBuilder(EsFieldEnum fieldEnum) {
return AggregationBuilders
.cardinality(fieldEnum.count())
.field(fieldEnum.keyword());
}
/**
* 新建一个根据指定字段统计的聚合builder
*
* @param fieldEnum 字段枚举值
*/
public static AggregationBuilder newTermsBuilder(EsFieldEnum fieldEnum) {
return AggregationBuilders
.terms(fieldEnum.groupBy())
.field(fieldEnum.keyword());
}
private static final DecimalFormat df = new DecimalFormat("######0.00");
public static String formatDouble(Double number) {
if (number.equals(Double.NEGATIVE_INFINITY) || number.equals(Double.POSITIVE_INFINITY)) {
return "0";
}
return df.format(number);
}
/**
* 请求ES并获取通用柱状图结果
*
* @param client es客户端对象
* @param searchRequest 请求参数
*/
public static List<CurrencyChartVo> queryAndGetCurrencyChartResult(RestHighLevelClient client, SearchRequest searchRequest, EsFieldEnum fieldEnum) {
List<CurrencyChartVo> result = new LinkedList<>();
SearchResponse searchResponse;
try {
searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
Terms terms = searchResponse.getAggregations().get(fieldEnum.groupBy());
for (Terms.Bucket buck : terms.getBuckets()) {
String xvalue = buck.getKeyAsString();
long yvalue = buck.getDocCount();
result.add(new CurrencyChartVo(xvalue, yvalue));
}
} catch (IOException e) {
ThrowQueryException();
}
return result;
}
/**
* 获取根据指定维度统计的结果
* <p>
* 当筛选字段与分组字段相同时,使用该方法,传入统一的字段枚举{@link EsFieldEnum}
*
* <b>这里的筛选字段使用的是模糊查询</b>
*
* @param client es客户端
* @param startTime 开始时间
* @param endTime 结束时间
* @param para 筛选字段参数
* @param groupByFieldEnum 用于分组的字段(维度字段)
*/
public static List<CurrencyChartVo> getErrCountChartResult(RestHighLevelClient client,
Date startTime,
Date endTime,
String para,
EsFieldEnum groupByFieldEnum) {
RangeQueryBuilder errQuery = QueryBuilders.rangeQuery(EsFieldEnum.ORIGIN_STATUS.getName()).gte(HttpStatus.HTTP_BAD_REQUEST);
return getCurrencyChartResult(client, errQuery, startTime, endTime, para, groupByFieldEnum);
}
/**
* 获取根据指定维度统计的结果
* <p>
* 当筛选字段与分组字段不同时,使用该方法,分别传入其字段枚举{@link EsFieldEnum}
*
* <b>这里的筛选字段使用的是全值匹配</b>
*
* @param client es客户端
* @param startTime 开始时间
* @param endTime 结束时间
* @param para 筛选字段值
* @param paraFieldEnum 筛选字段枚举值
* @param groupByFieldEnum 用于分组的字段(维度字段)
*/
public static List<CurrencyChartVo> getErrCountChartResult(RestHighLevelClient client,
Date startTime,
Date endTime,
String para,
EsFieldEnum paraFieldEnum,
EsFieldEnum groupByFieldEnum) {
RangeQueryBuilder errQuery = QueryBuilders.rangeQuery(EsFieldEnum.ORIGIN_STATUS.getName()).gte(HttpStatus.HTTP_BAD_REQUEST);
return getCurrencyChartResult(client, errQuery, startTime, endTime, para, paraFieldEnum, groupByFieldEnum);
}
/**
* 获取根据指定维度统计的结果
* <p>
* 当筛选字段与分组字段相同时,使用该方法,传入统一的字段枚举{@link EsFieldEnum}
*
* <b>这里的筛选字段使用的是模糊查询</b>
*
* @param client es客户端
* @param startTime 开始时间
* @param endTime 结束时间
* @param para 筛选字段参数
* @param groupByFieldEnum 用于分组的字段(维度字段)
*/
public static List<CurrencyChartVo> getCurrencyChartResult(RestHighLevelClient client,
Date startTime,
Date endTime,
String para,
EsFieldEnum groupByFieldEnum) {
return getCurrencyChartResult(client, null, startTime, endTime, para, groupByFieldEnum);
}
/**
* 获取根据指定维度统计的结果
* <p>
* 当筛选字段与分组字段不同时,使用该方法,分别传入其字段枚举{@link EsFieldEnum}
*
* <b>这里的筛选字段使用的是全值匹配</b>
*
* @param client es客户端
* @param startTime 开始时间
* @param endTime 结束时间
* @param para 筛选字段值
* @param paraFieldEnum 筛选字段枚举值
* @param groupByFieldEnum 用于分组的字段(维度字段)
*/
public static List<CurrencyChartVo> getCurrencyChartResult(RestHighLevelClient client,
Date startTime,
Date endTime,
String para,
EsFieldEnum paraFieldEnum,
EsFieldEnum groupByFieldEnum) {
return getCurrencyChartResult(client, null, startTime, endTime, para, paraFieldEnum, groupByFieldEnum);
}
/**
* 获取根据指定维度统计的结果
* <p>
* 当筛选字段与分组字段相同时,使用该方法,传入统一的字段枚举{@link EsFieldEnum}
*
* <b>这里的筛选字段使用的是模糊查询</b>
*
* @param client es客户端
* @param startTime 开始时间
* @param endTime 结束时间
* @param para 筛选字段参数
* @param groupByFieldEnum 用于分组的字段(维度字段)
*/
public static List<CurrencyChartVo> getCurrencyChartResult(RestHighLevelClient client,
QueryBuilder otherCondition,
Date startTime,
Date endTime,
String para,
EsFieldEnum groupByFieldEnum) {
SearchRequest searchRequest = newRequest();
// 该searchSourceBuilder.size() = 0, 即数据条数为0,我们只需要聚合函数的结果
SearchSourceBuilder searchSourceBuilder = newAggSearchBuilder();
BoolQueryBuilder queryBuilder = newBoolQuery(startTime, endTime);
if (StringUtils.isNotBlank(para)) {
queryBuilder.must(QueryBuilders.wildcardQuery(groupByFieldEnum.keyword(), toLikeParam(para)));
}
if (otherCondition != null) {
queryBuilder.must(otherCondition);
}
searchSourceBuilder.query(queryBuilder);
searchSourceBuilder.aggregation(newTermsBuilder(groupByFieldEnum));
searchRequest.source(searchSourceBuilder);
return queryAndGetCurrencyChartResult(client, searchRequest, groupByFieldEnum);
}
/**
* 将参数加上左右模糊查询
*/
public static String toLikeParam(String para) {
return StringPool.ASTERISK + para + StringPool.ASTERISK;
}
/**
* 获取根据指定维度统计的结果
* <p>
* 当筛选字段与分组字段不同时,使用该方法,分别传入其字段枚举{@link EsFieldEnum}
*
* <b>这里的筛选字段使用的是全值匹配</b>
*
* @param client es客户端
* @param startTime 开始时间
* @param endTime 结束时间
* @param para 筛选字段值
* @param paraFieldEnum 筛选字段枚举值
* @param groupByFieldEnum 用于分组的字段(维度字段)
*/
public static List<CurrencyChartVo> getCurrencyChartResult(RestHighLevelClient client,
QueryBuilder otherCondition,
Date startTime,
Date endTime,
String para,
EsFieldEnum paraFieldEnum,
EsFieldEnum groupByFieldEnum) {
SearchRequest searchRequest = newRequest();
// 该searchSourceBuilder.size() = 0, 即数据条数为0,我们只需要聚合函数的结果
SearchSourceBuilder searchSourceBuilder = newAggSearchBuilder();
BoolQueryBuilder queryBuilder = newBoolQuery(startTime, endTime);
if (StringUtils.isNotBlank(para)) {
queryBuilder.must(QueryBuilders.termQuery(paraFieldEnum.keyword(), para));
}
if (otherCondition != null) {
queryBuilder.must(otherCondition);
}
searchSourceBuilder.query(queryBuilder);
searchSourceBuilder.aggregation(newTermsBuilder(groupByFieldEnum));
searchRequest.source(searchSourceBuilder);
return queryAndGetCurrencyChartResult(client, searchRequest, groupByFieldEnum);
}
/**
* 获取根据指定维度的响应时间统计信息
* <p>
* 当筛选字段与分组字段不同时,使用该方法,分别传入其字段枚举{@link EsFieldEnum}
*
* <b>这里的筛选字段使用的是全值匹配</b>
*
* @param client es客户端
* @param startTime 开始时间
* @param endTime 结束时间
* @param para 筛选字段值
* @param groupByFieldEnum 用于分组的字段(维度字段)
*/
public static List<ResponseTimeVo> getRespTimeResult(RestHighLevelClient client,
Date startTime,
Date endTime,
String para,
EsFieldEnum groupByFieldEnum) {
List<ResponseTimeVo> result = new LinkedList<>();
SearchRequest searchRequest = newRequest();
SearchSourceBuilder searchSourceBuilder = newAggSearchBuilder();
BoolQueryBuilder queryBuilder = newBoolQuery(startTime, endTime);
if (StringUtils.isNotBlank(para)) {
queryBuilder.must(QueryBuilders.wildcardQuery(groupByFieldEnum.keyword(), toLikeParam(para)));
}
searchSourceBuilder.query(queryBuilder);
//分组
resTimeResultHandler(client, groupByFieldEnum, result, searchRequest, searchSourceBuilder);
return result;
}
/**
* 获取根据指定维度的响应时间统计信息
* <p>
* 当筛选字段与分组字段不同时,使用该方法,分别传入其字段枚举{@link EsFieldEnum}
*
* <b>这里的筛选字段使用的是全值匹配</b>
*
* @param client es客户端
* @param startTime 开始时间
* @param endTime 结束时间
* @param para 筛选字段值
* @param paraFieldEnum 筛选字段枚举值
* @param groupByFieldEnum 用于分组的字段(维度字段)
*/
public static List<ResponseTimeVo> getRespTimeResult(RestHighLevelClient client,
Date startTime,
Date endTime,
String para,
EsFieldEnum paraFieldEnum,
EsFieldEnum groupByFieldEnum) {
List<ResponseTimeVo> result = new LinkedList<>();
SearchRequest searchRequest = newRequest();
SearchSourceBuilder searchSourceBuilder = newAggSearchBuilder();
BoolQueryBuilder queryBuilder = newBoolQuery(startTime, endTime);
if (StringUtils.isNotBlank(para)) {
queryBuilder.must(QueryBuilders.wildcardQuery(paraFieldEnum.keyword(), toLikeParam(para)));
}
searchSourceBuilder.query(queryBuilder);
resTimeResultHandler(client, groupByFieldEnum, result, searchRequest, searchSourceBuilder);
return result;
}
private static void resTimeResultHandler(RestHighLevelClient client, EsFieldEnum groupByFieldEnum, List<ResponseTimeVo> result, SearchRequest searchRequest, SearchSourceBuilder searchSourceBuilder) {
//分组
TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms(groupByFieldEnum.groupBy()).field(groupByFieldEnum.keyword());
//最大值
aggregationBuilder.subAggregation(AggregationBuilders.max(EsFieldEnum.DURATION.max()).field(EsFieldEnum.DURATION.getName()));
//最小值
aggregationBuilder.subAggregation(AggregationBuilders.max(EsFieldEnum.DURATION.min()).field(EsFieldEnum.DURATION.getName()));
//平均值
aggregationBuilder.subAggregation(AggregationBuilders.avg(EsFieldEnum.DURATION.avg()).field(EsFieldEnum.DURATION.getName()));
searchSourceBuilder.aggregation(aggregationBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse;
try {
searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
Terms terms = searchResponse.getAggregations().get(groupByFieldEnum.groupBy());
for (Terms.Bucket buck : terms.getBuckets()) {
String xvalue = buck.getKeyAsString();
ParsedSingleValueNumericMetricsAggregation max = buck.getAggregations().get(EsFieldEnum.DURATION.max());
ParsedSingleValueNumericMetricsAggregation min = buck.getAggregations().get(EsFieldEnum.DURATION.min());
ParsedSingleValueNumericMetricsAggregation avg = buck.getAggregations().get(EsFieldEnum.DURATION.avg());
result.add(
new ResponseTimeVo(
xvalue,
formatDouble(max.value()),
formatDouble(min.value()),
formatDouble(avg.value())
)
);
}
} catch (IOException e) {
ThrowQueryException();
}
}
public static void ThrowQueryException() {
throw new AuthBankException("ES请求错误,请联系管理员!");
}
}
封装完后,实际业务代码就非常少了,就是各种传参:
总结
ES的API功能非常多,目前暂时只介绍了部分查询功能,后续会陆续丰富内容,一键三连不迷路哦~