Elasticsearch 客户端的版本 7.6.2 聚合函数使用

Elasticsearch 客户端的版本 7.6.2 聚合函数使用

最近公司使用es查询数据,各种聚合,图表。使用RestHighLevelClient java客户端。

这里记录一下es的聚合函数使用。

springboot 版本 2.3.0.RELEASE

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

在这里插入图片描述

客户端的版本 7.6.2

es配置类
package com.huize.titan.mobile.server.config;

import lombok.extern.slf4j.Slf4j;
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;
import org.springframework.context.annotation.Primary;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

import java.util.ArrayList;
import java.util.List;


/**
 * @Author aiyuan
 * @Date 2021/7/6 9:12
 **/
@Configuration
@Slf4j
public class ElasticSearchConfig {

    /** 集群地址,如果有多个用“,”隔开 */
    @Value("${elasticsearch.web.address}")
    private String webAddress;

    /** 集群地址,如果有多个用“,”隔开 */
    @Value("${elasticsearch.app.address}")
    private String appAddress;

    /** 连接超时时间 */
    @Value("${elasticsearch.connectTimeout}")
    private int connectTimeout;

    /** Socket 连接超时时间 */
    @Value("${elasticsearch.socketTimeout}")
    private int socketTimeout;

    /** 获取连接的超时时间 */
    @Value("${elasticsearch.connectionRequestTimeout}")
    private int connectionRequestTimeout;

    /** 最大连接数 */
    @Value("${elasticsearch.maxConnectNum}")
    private int maxConnectNum;

    /** 最大路由连接数 */
    @Value("${elasticsearch.maxConnectPerRoute}")
    private int maxConnectPerRoute;

    @Primary
    @Bean(name = "webRestHighLevelClient")
    public RestHighLevelClient webRestHighLevelClient() {
        log.info("webRestHighLevelClient注入--:{}",webAddress);
        return restHighLevelClient(webAddress);
    }

    @Bean(name = "appRestHighLevelClient")
    public RestHighLevelClient appRestHighLevelClient() {
        log.info("appRestHighLevelClient注入--:{}",appAddress);
       return restHighLevelClient(appAddress);
    }



    public RestHighLevelClient restHighLevelClient(String address) {
        // 拆分地址
        List<HttpHost> hostLists = new ArrayList<>();
        String[] hostList = address.split(",");
        for (String addr : hostList) {
            String host = addr.split(":")[0];
            String port = addr.split(":")[1];
            hostLists.add(new HttpHost(host, Integer.parseInt(port)));
        }
        // 转换成 HttpHost 数组
        HttpHost[] httpHost = hostLists.toArray(new HttpHost[]{});
        // 构建连接对象
        RestClientBuilder builder = RestClient.builder(httpHost);
        // 异步连接延时配置
        builder.setRequestConfigCallback(requestConfigBuilder -> {
            requestConfigBuilder.setConnectTimeout(connectTimeout);
            requestConfigBuilder.setSocketTimeout(socketTimeout);
            requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeout);
            return requestConfigBuilder;
        });
        // 异步连接数配置
        builder.setHttpClientConfigCallback(httpClientBuilder -> {
            httpClientBuilder.setMaxConnTotal(maxConnectNum);
            httpClientBuilder.setMaxConnPerRoute(maxConnectPerRoute);
            return httpClientBuilder;
        });
        return new RestHighLevelClient(builder);
    }
}

​ 因为这里用到了不同的es集群,所以配置了两个客户端。

普通的terms聚合
	/**
     * @param queryBuilder 查询条件
     * @date 2021/1/7 16:44
     * @author aiyuan
     */
    public List<ApplicationLogBO> commonAppLogRanking(QueryBuilder queryBuilder){
        log.info("查询应用日志排行---> start");
        List<ApplicationLogBO> resultData = new ArrayList<>();
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //添加查询条件
        sourceBuilder.query(queryBuilder);
        //添加查询聚合 采用的是terms 聚合函数
        AggregationBuilder aggregation = AggregationBuilders
                .terms(ESConstant.POD_NAME) //别名 再返回之中取出Bucket名字
                .field(ESConstant.NAMESPACE) //es中 需要分组的字段 可以采用  “.keyword” 完全匹配
            	//在上一次聚合后 再次聚合
                .subAggregation(AggregationBuilders
                                .terms(ESConstant.APP_NAME) //别名 再返回之中取出Bucket名字
                                .field(ESConstant.APP_AGGS) //es中 需要分组的字段 可以采用  “.keyword” 完全匹配
                                .size(Integer.MAX_VALUE))
            	/**
            		public static BucketOrder count(boolean asc) {
      				  	return asc ? InternalOrder.COUNT_ASC : InternalOrder.COUNT_DESC;
    				}			
    			*/
                .order(BucketOrder.count(false))//排序方式
            	.size(Integer.MAX_VALUE);
        sourceBuilder.aggregation(aggregation);//将分组函数加入查询构建起中
        SearchRequest request = new SearchRequest();
        //索引名称 前缀匹配  可以使用通配符 * 例如:“error-log*” 
        request.indices(ERROR_LOG);
        request.source(sourceBuilder);
        SearchResponse search;
        try {
            search = appRestHighLevelClient.search(request, RequestOptions.DEFAULT);
            Terms podTerms = search.getAggregations().get(ESConstant.POD_NAME);//上边AggregationBuilders中 取得别名
            for (Terms.Bucket podTerm : podTerms.getBuckets()) {
                Terms appTerms = podTerm.getAggregations().get(ESConstant.APP_NAME);//上边AggregationBuilders中 取得别名
                for (Terms.Bucket appTerm : appTerms.getBuckets()) {
                    ApplicationLogBO applicationLogBO = ApplicationLogBO.builder()
                            .podName(podTerm.getKeyAsString())
                            .appName(appTerm.getKeyAsString())
                            .count((int) appTerm.getDocCount())
                            .build();
                    resultData.add(applicationLogBO);
                }

            }
            log.info("查询应用日志排行---> end");
            return resultData;
        } catch (IOException e) {
            log.error("查询应用日志排行失败--->{}",e.getMessage(),e);
            return resultData;
        }
    }

但是有一个图表,需要根据时间,分成指定的时间段分组统计次数。我一想不都是根据每分钟、每小时、每天… 这样来的吗?

然后开始百度。。。。。

然后就看到了这个

GET /cars/transactions/_search
{
   "size" : 0,
   "aggs": {
      "sales": {
         "date_histogram": {
            "field": "sold",
            "interval": "month", 
            "format": "yyyy-MM-dd" 
            "extended_bounds" : { 
                "min" : "2014-01-01",
                "max" : "2014-12-31"
            }
         }
      }
   }
}

一看AggregationBuilder 聚合构建器中看到一叫DateHistogramAggregationBuilder
在这里插入图片描述

之后就根据dsl语句,写出如下 聚合构建器

	AggregationBuilders.dateHistogram("time") //别名 和之前的一样
                        .field(ESConstant.TIME_AGGS)
                        .fixedInterval(DateHistogramInterval.MINUTE)//聚合时间
                        .format("HH:mm:ss"); //时间格式

猛地一看还是没有指定时间段呀 这可咋整!!!

再一看DateHistogramInterval 是常量 但不是枚举定义的 进去一看问题解决 收工下班!
在这里插入图片描述

	AggregationBuilders.dateHistogram("time") //别名 和之前的一样
                        .field(ESConstant.TIME_AGGS)
                        .fixedInterval(DateHistogramInterval.seconds(30))//聚合时间
                        .format("HH:mm:ss"); //时间格式

返回值跟之前获取就行

不过从SearchResponse 获取 接受类型是 Histogram

Histogram timeTerms =  search.getAggregations().get("time");

结果如下:
在这里插入图片描述
之前es用的比较少,这次也学习。end!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值