1. 桶
桶(Bucket)聚合:用来对文档做分组
- TermAggregation:按照文档字段值分组,例如按照品牌值分组、按照国家分组
- Date Histogram:按照日期阶梯分组,例如一周为一组,或者一月为一组
# 聚合, 只能对keyword进行聚合
GET /items/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"category.keyword": "手机"
}
},
{
"range": {
"price": {
"gte": 100000
}
}
}
]
}
},
"size": 0,
"aggs": {
"category_agg": {
"terms": {
"field": "brand.keyword",
"size": 20
}
}
}
}
2. Metric聚合
统计了价格高于3000的手机品牌,形成了一个个桶。现在我们需要对桶内的商品做运算,获取每个品牌价格的最小值、最大值、平均值。
这就要用到Metric聚合了,例如stat聚合,就可以同时获取min、max、avg等结果。
# 聚合, 只能对keyword进行聚合
GET /items/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"category.keyword": "手机"
}
},
{
"range": {
"price": {
"gte": 100000
}
}
}
]
}
},
"size": 0,
"aggs": {
"category_agg": {
"terms": {
"field": "brand.keyword",
"size": 20
},
"aggs": {
"price_status": {
"stats": {
"field": "price"
}
}
}
}
}
}
3. 使用JavaRestClient
@Test
void testAgg() throws IOException {
// 1. 创建 Request
SearchRequest request = new SearchRequest("items");
// 2. 组织请求参数
request.source().query(
QueryBuilders.boolQuery()
.filter(QueryBuilders.termQuery("category.keyword", "手机"))
.filter(QueryBuilders.rangeQuery("price").gte(100000))
).size(0);
// 2.1 聚合参数
request.source().aggregation(
AggregationBuilders.terms("brand_agg").field("brand.keyword").size(5)
);
// 3. 发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4. 解析响应
Aggregations aggregations = response.getAggregations();
// 4.1 获取品牌聚合
Terms brandTerms = aggregations.get("brand_agg");
// 5.2 获取聚合中的桶
List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
// 5.3 遍历桶内数据
for(Terms.Bucket bucket:buckets) {
// 5.4 获取桶内key
String brand = bucket.getKeyAsString();
System.out.println("brand=" + brand);
long count = bucket.getDocCount();
System.out.println("count=" + count);
}
}