
本文共 4687 字,大约阅读时间需要 15 分钟。
数据聚合
1.1 基本概念
1.1.1 聚合分类
聚合(aggregations)是对文档数据进行统计分析和运算的重要功能。类似于 MySQL中的聚合函数(如 avg、max 等),Elasticsearch也提供了丰富的聚合功能。
Elasticsearch中的聚合分为三大类,分别是桶(Bucket)聚合、度量(Metric)聚合和管道(Pipeline)聚合。
桶(Bucket)聚合
桶聚合用于对文档进行分组,类似于 MySQL中的 group by
操作。常见的桶聚合类型有:
TermAggregation
:按照文档字段值(如品牌名称)分组。DataHistogram
:按日期阶梯分组(如一天为一组、一周为一组)。
度量(Metric)聚合
度量聚合用于对分组后的文档数据进行计算(如求最大值、最小值、平均值等),与 MySQL中的聚合函数类似。Elasticsearch还提供一个特殊的度量聚合 stats
,可以同时计算多个统计指标。
管道(Pipeline)聚合
管道聚合用于对其他聚合的结果进行聚合。例如,先对酒店按品牌分组(桶聚合),然后对每个品牌的酒店价格进行平均值计算(度量聚合),最后再对价格平均值进行排序(度量聚合)。
注:管道聚合的使用较少,不是黑马旅游案例的重点。
1.1.2 特点
需要注意的是,参与聚合的字段必须是不可分词的字段(如字符串字段、日期字段、布尔字段等)。因此,日期、数值、布尔类型的字段不能参与聚合。
1.2 DSL 实现 Bucket 聚合
在 Elasticsearch 中,通过 DSL(Domain Specific Language)实现聚合功能。以下是 Bucket 聚合的基本语法和使用场景。
1.2.1 Bucket 聚合基础语法
GET /索引库名/_search { "size": 0, "aggs": { "自定义聚合名": { "terms": { "field": "字段名", "size": 20 } } }}
- 聚合名称:自定义聚合名。
- 聚合类型:
terms
表示按字段值分组。 - 聚合字段:参与聚合的字段。
- 聚合结果数量:
size
可设置为具体数字,值超过总数无影响。
示例:按酒店品牌进行分组,字段为 brand
。
1.2.2 Bucket 聚合结果排序
默认情况下,Bucket 聚合会统计每组文档数量(_count
),并根据 _count
降序排序。
示例:按酒店品牌分组,并按照每个品牌的酒店数量进行升序排序。
1.2.3 Bucket 聚合限定范围
默认情况下,Bucket 聚合会对索引库的所有文档进行聚合。可以通过查询条件对聚合范围进行限定,以减少对内存的消耗。
示例:搜索价格 小于等于 200 的酒店,并按品牌分类。
1.3 DSL 实现 Metrics 聚合
度量聚合是对分组后的每组文档数据进行计算。例如,查询每个品牌用户评分的最小值、最大值、平均值等。
1.3.1 度量聚合语法
GET /索引库名/_search { "size": 0, "aggs": { "自定义聚合名": { "terms": { "field": "字段名", "size": 20 }, "aggs": { "自定义度量聚合": { "stats": { "field": "score" } } } } }}
步骤:
terms
聚合按字段值分组。stats
聚合)。示例:按品牌分组,计算每组用户评分的平均值。
1.4 基于 JavaRestClient 实现聚合
1.4.1 组装请求
示例代码:
@Testpublic void testAggregation() throws IOException { SearchRequest request = new SearchRequest("hotel"); request.source().size(0); request.source().aggregation( AggregationBuilders .terms("brandAgg") .field("brand") .size(10)); SearchResponse response = client.search(request, RequestOptions.DEFAULT); handlerResponse(response);}
1.4.2 解析响应
// 解析聚合结果Aggregations aggregations = response.getAggregations();Terms terms = aggregations.get("brandAgg");Listbuckets = terms.getBuckets();for (Bucket bucket : buckets) { String key = bucket.getKeyAsString(); System.out.println(key);}
1.5 黑马旅游案例
1.5.1 需求
通过聚合索引库中的酒店数据,动态生成搜索页面的品牌、城市、星级信息。
1.5.2 对接前端接口
请求参数:
{ "brand": ["王国酒店", "大酒店集团"], "city": ["上海", "北京"], "starName": [1, 2, 3]}
响应格式:
{ "城市": ["上海", "北京"], "品牌": ["王国酒店", "大酒店集团"], "星级": ["一星级", "二星级", "三星级"]}
1.5.3 编写 controller
示例代码:
@RequestMapping("/filters")public Map> filters(@RequestBody RequestParams params) { return hotelService.filters(params);}
1.5.4 添加 filters 接口
public interface IHotelService extends IService{ PageResult search(RequestParams params); Map > filters(RequestParams params);}
1.5.5 实现接口
@Overridepublic Map> filters(RequestParams params) { try { SearchRequest request = new SearchRequest("hotel"); handlerBoolQueryBuilder(request, params); request.source().size(0); buildAggregation(request); SearchResponse response = client.search(request, RequestOptions.DEFAULT); Map > result = new HashMap<>(); Aggregations aggregations = response.getAggregations(); List brandAgg = getAggListByName(aggregations, "brandAgg"); result.put("brand", brandAgg); List cityAgg = getAggListByName(aggregations, "cityAgg"); result.put("city", cityAgg); List starAgg = getAggListByName(aggregations, "starAgg"); result.put("starName", starAgg); return result; } catch (IOException e) { System.out.println("[HotelService] 酒店数据聚合失败!"); e.printStackTrace(); return null; }}private List getAggListByName(Aggregations aggregations, String aggName) { Terms terms = aggregations.get(aggName); List buckets = terms.getBuckets(); List result = new ArrayList<>(); for (Bucket bucket : buckets) { result.add(bucket.getKeyAsString()); } return result;}private void buildAggregation(SearchRequest request) { request.source().aggregation( AggregationBuilders .terms("brandAgg") .field("brand") .size(100)); request.source().aggregation( AggregationBuilders .terms("cityAgg") .field("city") .size(100)); request.source().aggregation( AggregationBuilders .terms("starAgg") .field("starName") .size(100));}
通过以上方法,可以实现酒店数据的动态聚合,满足前端页面对品牌、城市、星级等字段的实时查询需求。
发表评论
最新留言
关于作者
