数据聚合
聚合的种类
DSL实现Bucket聚合
如图所示,设置了10个桶,那么就显示了数量最多的前10个桶,品牌含有7天酒店的有30家,
品牌含有如家的也有30家。
修改排序规则
限定聚合范围
DSL实现Metrics聚合
如下案例要求对不同的品牌进行统计,所以要进行分组。
如图所示,要对桶的平均评分做排序,要使用不同桶的平均评分
RestClient实现聚合
请求组装
java
@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.解析结果
System.out.println(response);
}
结果解析
java
@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获取key
String key = bucket.getKeyAsString();
System.out.println(key);
}
}
多条件聚合
在Service中
将公共代码抽取出来,提高复用性
java
@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();
//5.1根据品牌名称获取品牌结果
List<String> brandList = getAggByName(aggregations,"brandAgg");
result.put("品牌",brandList);
//5.2根据品牌名称获取品牌结果
List<String> cityList = getAggByName(aggregations,"cityAgg");
result.put("城市",cityList);
//5.3根据品牌名称获取品牌结果
List<String> starList = getAggByName(aggregations,"starAgg");
result.put("星级",starList);
return result;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static 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获取key
String key = bucket.getKeyAsString();
brandList.add(key);
}
return brandList;
}
在一个测试类中
java
@SpringBootTest
class HotelDemoApplicationTests {
@Autowired
private IHotelService hotelService;
@Test
void contextLoads() {
Map<String, List<String>> filters = hotelService.filters();
System.out.println(filters);
}
}
运行得到
带过滤条件的聚合
在查询的时候要在查询结果上做聚合,不应该直接将所有数据的聚合结果返回。
所以就是加上query参数。
Controller中
传递的参数和正常参数一模一样
java
@PostMapping("filters")
public Map<String, List<String>> getFilters(@RequestBody RequestParams Params)
{
return hotelService.filters(Params);
}
Service中
添加传递参数,并且新设置了2.3query,使用搜索时同款的query设置方法
java
@Override
public Map<String, List<String>> filters(RequestParams Params) {
try {
//1.准备Request
SearchRequest request = new SearchRequest("hotel");
//2.准备DSl
//2.1设置size
request.source().size(0);
//2.2聚合
buildAggregation(request);
//2.3query
buildBasicQuery(Params, request);
//3.发出请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//4.解析结果
Map<String, List<String>>result=new HashMap<>();
Aggregations aggregations = response.getAggregations();
//5.1根据品牌名称获取品牌结果
List<String> brandList = getAggByName(aggregations,"brandAgg");
result.put("品牌",brandList);
//5.2根据品牌名称获取品牌结果
List<String> cityList = getAggByName(aggregations,"cityAgg");
result.put("城市",cityList);
//5.3根据品牌名称获取品牌结果
List<String> starList = getAggByName(aggregations,"starAgg");
result.put("星级",starList);
return result;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
结果测试
根据搜索框和过滤条件成功过滤