该示例中用到的索引hotel和代码仓库请参考如下文章:
通过hotel-demo演示RestClient操作Elasticsearch
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html
聚合是对文档数据的统计、分析、计算
必须是:
# 聚合功能
GET /hotel/_search
{
"size":0,
"aggs": {
"brandAgg": {
"terms": {
"field": "brand",
"size": 20
}
}
}
}
当size设置10时,表示只返回10个分组,这个时候可以看到**“sum_other_doc_count” : 39当我们吧size改为20之后,表示返回20个分组,则"sum_other_doc_count" : 0**;注意结果中默认是根据每组的文档数量降序
默认情况下,Bucket聚合会统计Bucket内的文档数量,记为_count,并按照_count降序排序
我们可以修改结果排序方式:
# 聚合功能,自定义排序规则
GET /hotel/_search
{
"size":0,
"aggs": {
"brandAgg": {
"terms": {
"field": "brand",
"order": {
"_count": "asc"
},
"size": 10
}
}
}
}
默认情况下,Bucket聚合是对索引库的所有文档做聚合,我们可以限定要聚合的文档范围,只要添加query条件即可
比如我们限定价格在200以上的
# 聚合功能,限定聚合范围
GET /hotel/_search
{
"query":{
"range": {
"price": {
"lte": 200
}
}
},
"size":0,
"aggs": {
"brandAgg": {
"terms": {
"field": "brand",
"order": {
"_count": "asc"
},
"size": 10
}
}
}
}
# 聚合功能 嵌套聚合metric
GET /hotel/_search
{
"size":0,
"aggs": {
"brandAgg": {
"terms": {
"field": "brand",
"size": 10
},
"aggs":{
"scoreAgg":{
"stats": {
"field": "score"
}
}
}
}
}
}
按照打分的平均分降序
# 聚合功能 嵌套聚合metric,按照平均分降序
GET /hotel/_search
{
"size":0,
"aggs": {
"brandAgg": {
"terms": {
"field": "brand",
"size": 10,
"order": {
"scoreAgg.avg": "desc"
}
},
"aggs":{
"scoreAgg":{
"stats": {
"field": "score"
}
}
}
}
}
}
/**
* 品牌聚合
*/
@Test
void testAggregation() throws IOException {
// 1. 准备Request
SearchRequest request = new SearchRequest("hotel");
// 2. 准备DSL
// 2.1. 设置size
request.source().size(0);
// 2.2. 聚合
request.source().aggregation(AggregationBuilders
.terms("brandAgg")
.field("brand")
.size(10)
);
// 3. 发出请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4. 解析结果
Aggregations aggregations = response.getAggregations();
// 4.1. 根据聚合名称获取聚合结果
Terms brandTerms = aggregations.get("brandAgg");
// 4.2. 获取buckets
List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
// 4.3. 遍历
for(Terms.Bucket bucket: buckets){
// 4.4. 获取可以
String key = bucket.getKeyAsString();
System.out.println(key);
}
}
@Override
public Map<String, List<String>> filters() {
try{
// 1. 准备Request
SearchRequest request = new SearchRequest("hotel");
// 2. 准备DSL
// 2.1. 设置size
request.source().size(0);
// 2.2. 聚合
buildAggregation(request);
// 3. 发出请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4. 解析结果
Map<String, List<String>> result = new HashMap<>();
Aggregations aggregations = response.getAggregations();
// 4.1 根据品牌名称,获取品牌结果
List<String> brandList = getAggByName(aggregations,"brandAgg");
result.put("品牌",brandList);
// 4.2 根据城市名称,获取品牌结果
List<String> cityList = getAggByName(aggregations,"cityAgg");
result.put("城市",cityList);
// 4.3 根据星级名称,获取品牌结果
List<String> starList = getAggByName(aggregations,"starAgg");
result.put("星级",starList);
return result;
}catch (IOException e){
throw new RuntimeException(e);
}
}
private List<String> getAggByName(Aggregations aggregations, String aggName) {
// 4.1. 根据聚合名称获取聚合结果
Terms brandTerms = aggregations.get(aggName);
// 4.2. 获取buckets
List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
// 4.3. 遍历
List<String> brandList = new ArrayList<>();
for(Terms.Bucket bucket: buckets){
// 4.4. 获取可以
String key = bucket.getKeyAsString();
brandList.add(key);
}
return brandList;
}
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)
);
}
{品牌=[7天酒店, 如家, 皇冠假日, 速8, 万怡, 华美达, 和颐, 万豪, 喜来登, 希尔顿, 汉庭, 凯悦, 维也纳, 豪生, 君悦, 万丽, 丽笙], 星级=[], 城市=[上海, 北京, 深圳]}
// controller
@PostMapping("/filters")
public Map<String, List<String>> getFilters(@RequestBody RequestParams params){
return hotelService.filters(params);
}
...
...
...
// service
@Override
public Map<String, List<String>> filters(RequestParams params) {
try{
// 1. 准备Request
SearchRequest request = new SearchRequest("hotel");
// 2. 准备DSL
// 2.1. query
buildBasicQuery(params,request);
// 2.2. 设置size
request.source().size(0);
// 2.3. 聚合
buildAggregation(request);
// 3. 发出请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4. 解析结果
Map<String, List<String>> result = new HashMap<>();
Aggregations aggregations = response.getAggregations();
// 4.1 根据品牌名称,获取品牌结果
List<String> brandList = getAggByName(aggregations,"brandAgg");
result.put("品牌",brandList);
// 4.2 根据城市名称,获取品牌结果
List<String> cityList = getAggByName(aggregations,"cityAgg");
result.put("城市",cityList);
// 4.3 根据星级名称,获取品牌结果
List<String> starList = getAggByName(aggregations,"starAgg");
result.put("星级",starList);
return result;
}catch (IOException e){
throw new RuntimeException(e);
}
}