当前位置: 首页 > news >正文

elasticsearch的数据聚合

聚合可以让我们极其方便的实现对数据的统计、分析、运算。例如:

  • 什么品牌的手机最受欢迎?

  • 这些手机的平均价格、最高价格、最低价格?

  • 这些手机每月的销售情况如何?

实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近实时搜索效果

聚合种类

聚合常见的有三类:

  • 桶(Bucket)聚合:用来对文档做分组

    • TermAggregation:按照文档字段值分组,例如按照品牌值分组、按照国家分组

    • Date Histogram:按照日期阶梯分组,例如一周为一组,或者一月为一组

  • 度量(Metric)聚合:用以计算一些值,比如:最大值、最小值、平均值等

    • Avg:求平均值

    • Max:求最大值

    • Min:求最小值

    • Stats:同时求max、min、avg、sum等

  • 管道(pipeline)聚合:其它聚合的结果为基础做聚合

注意:参加聚合的字段必须是keyword、日期、数值、布尔类型  

DSL实现聚合

语句

GET /hotel/_search
{"size": 0,"aggs": {"brandAgg": {"terms": {"field": "brand","size": 20}}}
}
  • 设置size为0,结果中不包含文档,只包含聚合结果
  • aggs定义聚合
  • brandAgg给聚合起个名字
  • terms聚合的类型,按照品牌值聚合,所以选择term
  • field参与聚合的字段
  • terms里面的sezi希望获取的聚合结果数量

发起请求的结果 

聚合结果排序

默认情况下,Bucket聚合会统计Bucket内的文档数量,记为count,并且按照count降序排序。

我们可以指定order属性,自定义聚合的排序方式,按照_count降序排列

GET /hotel/_search
{"size": 0, "aggs": {"brandAgg": {"terms": {"field": "brand","order": {"_count": "desc"  },"size": 20}}}
}

发起请求的结果, 按照_count降序排列。

限定聚合范围

默认情况下,Bucket聚合是对索引库的所有文档做聚合,但真实场景下,用户会输入搜索条件,因此聚合必须是对搜索结果聚合。那么聚合必须添加限定条件。我们可以限定要聚合的文档范围,只要添加query条件即可。

 只对200元以下的文档聚合

GET /hotel/_search
{"query": {"range": {"price": {"lte": 200  }}}, "size": 0, "aggs": {"brandAgg": {"terms": {"field": "brand","size": 20}}}
}

聚合得到的品牌明显变少了  

Metric聚合语法

现在我们需要对桶内的酒店做运算,获取每个品牌的用户评分的min、max、avg等值

 score_stats聚合是在brandAgg的聚合内部嵌套的子聚合。因为我们需要在每个桶分别计算

GET /hotel/_search
{"size": 0, "aggs": {"brandAgg": { "terms": { "field": "brand", "size": 20},"aggs": { "score_stats": { "stats": { "field": "score" }}}}}
}

我们还可以给聚合结果做个排序,例如按照每个桶的酒店平均分做排序,score_stats.avg对score聚合函数的平均值进行降序排序。

GET /hotel/_search
{"size": 0, "aggs": {"brandAgg": { "terms": { "field": "brand", "size": 20,"order": {"score_stats.avg": "desc"}},"aggs": { "score_stats": { "stats": { "field": "score" }}}}}
}

小结

aggs代表聚合,与query同级  

聚合必须的三要素:

  • 聚合名称

  • 聚合类型

  • 聚合字段

聚合可配置属性有:

  • size:指定聚合结果数量

  • order:指定聚合结果排序方式

  • field:指定聚合字段

java代码实现聚合

搜索页面的品牌、城市等信息不应该是在页面写死,而是通过聚合索引库中的酒店数据得来的  

controller类

import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import cn.itcast.hotel.service.IHotelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;
import java.util.Map;@RestController
@RequestMapping("/hotel")
public class HotelController {@Autowiredprivate IHotelService hotelService;@PostMapping("filters")public Map<String, List<String>> getFilters(@RequestBody RequestParams params){return hotelService.getFilters(params);}
}

service类

import cn.itcast.hotel.mapper.HotelMapper;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {@Autowiredprivate RestHighLevelClient client;@Overridepublic Map<String, List<String>> getFilters(RequestParams params) {try {// 1.准备RequestSearchRequest request = new SearchRequest("hotel");// 2.准备DSL// 2.1.query// buildBasicQuery(params, request);// 2.2.设置sizerequest.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);}}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));}private List<String> getAggByName(Aggregations aggregations, String aggName) {// 4.1.根据聚合名称获取聚合结果Terms brandTerms = aggregations.get(aggName);// 4.2.获取bucketsList<? extends Terms.Bucket> buckets = brandTerms.getBuckets();// 4.3.遍历List<String> brandList = new ArrayList<>();for (Terms.Bucket bucket : buckets) {// 4.4.获取keyString key = bucket.getKeyAsString();brandList.add(key);}return brandList;}}

发送请求,获得结果

http://www.lryc.cn/news/161709.html

相关文章:

  • 【网络编程·数据链路层】MAC帧/以太网协议/ARP协议/RARP协议
  • 算法:移除数组中的val的所有元素---双指针[2]
  • Python小知识 - Python爬虫进阶:如何克服反爬虫技术
  • SAP中的新旧事务码
  • day3_C++
  • 力扣题解(73. 矩阵置零),带注释
  • SpringMVC应用
  • 百度输入法全面升级,打造首个基于大模型的输入法原生应用
  • 如何解决GitHub 访问不了?小白教程
  • 龙芯指令集LoongArch——学习笔记(1)
  • ubuntu 20.04 docker安装emqx 最新版本或指定版本
  • 软件测试/测试开发丨学会与 AI 对话,高效提升学习效率
  • CEF内核和高级爬虫知识
  • 视频集中存储/云存储/磁盘阵列EasyCVR平台分组批量绑定/取消设备功能详解
  • 科技成果鉴定测试报告一般包含哪些测试内容?
  • IDEA中的“Deployment“ 将项目直接部署到服务器上
  • 密室逃脱小游戏
  • 【MyBatis】MyBatis项目结构的搭建
  • Vant组件库入门知识
  • Java字符串查找
  • 2023年7月京东投影仪行业品牌销售排行榜(京东大数据)
  • 设计模式-01简单工厂模式详解 详细代码对比
  • IPD-PDT-POP角色的名称、定位和职责说明书
  • 在MySQL中查看数据库和表的数据大小
  • Android前端音视频数据接入GB28181平台意义
  • Ubuntu 20.04上docker安装Redis
  • linux 压缩webfile文件夹 webfile.tar.gz和webfile.tar的区别
  • 基于SSM的农产品推广应用网站
  • 人大金仓分析型数据库身份鉴别
  • 基于SpringBoot的在线教育平台系统