第八章-分布式搜索引擎-深入ES:聚合、自动补全、拼音词典、DB数据同步、ES集群

数据聚合

帮助我们对海量的数据做统计和分析,结合kibana还可以形成可视化的图形报表

聚合的种类

聚合的字段一定是不分词的,不能是text的

比如说按照酒店数据按照品牌做分组,这个就属于桶的聚合

按照品牌分组后想算算不同品牌的 酒店的价格的平均值,或最大最小值怎么样--度量的聚合

算完平均值,想给排序,或者看看不同品牌平均值的最大最小值--这就是对度量结果再次聚合了就是管道了

除了这几种还有很多聚合的种类,这里只学习常用的

总结

聚合就是对索引库的数据做统计、分析、计算 

DSL实现聚合

aggs就是聚合的一个函数了

size是分页值,给0,显示的文档数据就是0条了,因为我的目的是看聚合,而不是看文档

聚合里的size如果不指定的话默认是10,就是控制显示的结果,比如说聚合结果又100多种,但是设置了这个size就是只显示前10条数据

三要素:聚合名称、聚合类型、聚合字段

聚合是对桶的聚合,是个数组,将来有很多个桶,默认排序规则是倒序排序 ,可以自定义排序规则 

修改排序规则 

 这里我们的聚合名称是brandAgg,将来如果想要定义多个聚合,就再加就好了

 可以限定文档的范围,只需要添加查询条件,我们加了酒店价格的范围,那么聚合范围也就少了,不用全查

 

DSL实现Metrics聚合(度量聚合)

聚合的嵌套,我们先对品牌做聚合,然后再他的基础上在对评分做聚合,评分的聚合aggs在第一个aggs里边

 聚合的嵌套,在第一个统计聚合的里边加平均值聚合,这样桶里的数据就多了好多 

我们再对得出结果的平均值做个排序,看看哪个酒店的评价最高

对桶里的数据做排序,以前是对_count排序,现在是对平均值排序

 注意,这种度量聚合嵌套,是在桶里边,定义的名字里边做的度量聚合

RestAPI实现聚合

request.source代表的是最大的json了

brand_agg当初我们用的就是terms类型,所以返回值也就是terms类型,根据聚合名称获取聚合结果 

 逐层解析json就可以了,我们可以先打印response

@Test
    void aggTest1() 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);
        // 解析结果
        Aggregations aggregations = response.getAggregations();
        // 根据聚合名称获取聚合结果,本来就terms类型,用terms接收那就
        // 根据brand_agg去获取桶
        Terms terms = aggregations.get("brandAgg");
        // 获取数组桶的内容
        List<? extends Terms.Bucket> buckets = terms.getBuckets();
        // 遍历每一个桶位
        for (Terms.Bucket bucket : buckets) {
            String keyAsString = bucket.getKeyAsString();
            System.out.println(keyAsString);
        }
    }

service 

 实现类

 利用command+option+m封装重复代码,使得更优雅

@Override
    public Map<String, List<String>> filters() {
        // 查出城市 city, 品牌 brand, 星级 startName
        try {
            SearchRequest request = new SearchRequest("hotel");
            // 针对多个字段做聚合,封装一下,就优雅了
            buildAggregation(request);
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            // 解析返回结果信息
            Aggregations aggregations = response.getAggregations();
            return buildResponse(aggregations);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    
    private void buildAggregation(SearchRequest request) {
        request.source().aggregation(
                AggregationBuilders.terms("cityAgg").field("city")
        ).aggregation(
                AggregationBuilders.terms("brandAgg").field("brand")
        ).aggregation(
                AggregationBuilders.terms("startNameAgg").field("starName")
        );
    }
    
    private Map<String, List<String>> buildResponse(Aggregations aggregations) {
        Map<String, List<String>> map = new HashMap<>();
        List<String> brandAggList = getAggByName(aggregations, "brandAgg");
        map.put("品牌", brandAggList);
        List<String> cityAggList = getAggByName(aggregations, "cityAgg");
        map.put("城市", cityAggList);
        List<String> startAggList = getAggByName(aggregations, "startNameAgg");
        map.put("星级", startAggList);
        return map;
    }

    private List<String> getAggByName(Aggregations aggregations, String params) {
        // 分别获取
        Terms cityAgg = aggregations.get(params);
        List<? extends Terms.Bucket> buckets = cityAgg.getBuckets();
        List<String> list = new ArrayList<>();
        for (Terms.Bucket bucket : buckets) {
            String keyAsString = bucket.getKeyAsString();
            list.add(keyAsString);
        }
        return list;
    }

利用单元测试注册service 然后就可以调用了,因为没有参数更方便测试,不用postMan就可以

对接前端接口

前端页面向服务端发送请求,查询品牌、城市、星级等字段的聚合结果

修改原来的filters接口,将其添加一个查询query即可,这个query得和之前的查询一样,直接用就可以了

也就是说我们在做聚合的时候是要加一些过滤条件的,去限制聚合的范围,条件就是查询的条件一样的,到时候记得把查询的条件封装出来,复用

@Override
    public Map<String, List<String>> filters(RequestParams requestParams) {
        // 查出城市 city, 品牌 brand, 星级 startName
        try {
            SearchRequest request = new SearchRequest("hotel");
            
            request.source().size(0);
            // 添加查询功能
            buildQueryBool(requestParams, request);
            
            
            
            // 针对多个字段做聚合,封装一下,就优雅了
            buildAggregation(request);
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            // json 有多个,那就是 jsonArr
            Aggregations aggregations = response.getAggregations();
            return buildResponse(aggregations);
        } catch
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值