ElasticSearch聚合统计Demo

590 阅读1分钟

ES聚合统计demo

统计某个字段的和,最小值,最大值,平均值等

GET /shop_order_v3/_search
{
  "query": {
    "bool": {
      "filter": {
        "bool": { 
            "must": [ 
              {
                "range": { 
                  "addTime": { 
                    "gt" : "2019-07-01 00:00:00",
                    "lt": "2020-07-07 00:00:00"
                  }
                }
              },
              { "term": { "storeId": "1" }}
            ]
        }
      }
    }
  },
  "size": 1, # 这里设置为1是为了输出文档内容,实际使用设为0
  "aggs": {
    "paymentPrice_stats": {
      "stats": {
        "field": "paymentPrice"
      }
    }
  }
}

ES输出

{
  "took" : 14,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 333,
    "max_score" : 0.0,
    "hits" : [
      {
        "_index" : "shop_order_v3",
        "_type" : "_doc",
        "_id" : "10939",
        "_score" : 0.0,
        "_source" : {
           # 部分字段 
          "id" : "10939",
          "paymentPrice" : 0.01,
          "postage" : 0.0,
          "salePrice" : 0.01,
          "statusDesc" : "订单已退款",
          "statusText" : "快递-已退款",
          "storeId" : 1,
          "userId" : 245
        }
      }
    ]
  },
  "aggregations" : {
    "paymentPrice_stats" : {
      "count" : 328,
      "min" : 0.01,
      "max" : 288.88,
      "avg" : 1.9077134146341463,
      "sum" : 625.73
    }
  }
}

java 实现

ES java Client版本是6.7.0

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>6.7.0</version>
</dependency>

java 实现

// ES日期需要填字符串
String searchYesterdayStartTime = DateFormatUtils.format(DateUtils.getDayStart(DateUtils.yesterday()), DateFormatConstant.YYYY_MM_DD_HH_MM_SS);
String searchYesterdayEndTime = DateFormatUtils.format(DateUtils.getDayEnd(DateUtils.yesterday()), DateFormatConstant.YYYY_MM_DD_HH_MM_SS);

// 构建查询条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder statisticsBoolQuery = QueryBuilders.boolQuery();
BoolQueryBuilder filterBuilder = QueryBuilders.boolQuery();
RangeQueryBuilder rangeQueryBuilder = new RangeQueryBuilder("addTime").from(searchYesterdayStartTime).to(searchYesterdayEndTime);
filterBuilder.must(rangeQueryBuilder);
filterBuilder.must(new TermQueryBuilder("storeId", storeId));
statisticsBoolQuery.filter(filterBuilder);
searchSourceBuilder.query(statisticsBoolQuery);
// 设置聚合类型与统计字段
searchSourceBuilder.aggregation(AggregationBuilders.stats("paymentPrice_stat").field("paymentPrice"));
// 隐藏搜索文档
searchSourceBuilder.size(0);

SearchRequest searchRequest = new SearchRequest(esIndexNameConfig.getShopOrder());
searchRequest.types("_doc");
searchRequest.source(searchSourceBuilder);
try {
    SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

    ParsedStats parsedStats = response.getAggregations().get("paymentPrice_stat");
    // 获取总和
    Double ordersSales = parsedStats.getSum();
    // 符合条件的文档数
    long ordersCount = parsedStats.getCount();

} catch (IOException e) {
    log.error("restHighLevelClient.search error {} ", e);
}

当Aggregation类型为stats时,response的统计结果需要用ParsedStats来接收,该类部分源码如下

package org.elasticsearch.search.aggregations.metrics.stats;

...
import org.elasticsearch.search.aggregations.ParsedAggregation;
...

public class ParsedStats extends ParsedAggregation implements Stats {

    protected long count; # 文档数
    protected double min; # 最小值
    protected double max; # 最大值
    protected double sum; # 总和
    protected double avg; # 平均值
    ...
}

设置聚合类型为stats时用ParsedStats来接收,其他聚合模型也都有对应的类。