• elasticsearch的数据聚合


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

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

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

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

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

    聚合种类

    聚合常见的有三类:

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

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

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

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

      • Avg:求平均值

      • Max:求最大值

      • Min:求最小值

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

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

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

    DSL实现聚合

    语句

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

    发起请求的结果 

    聚合结果排序

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

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

    1. GET /hotel/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "brandAgg": {
    6. "terms": {
    7. "field": "brand",
    8. "order": {
    9. "_count": "desc"
    10. },
    11. "size": 20
    12. }
    13. }
    14. }
    15. }

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

    限定聚合范围

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

     只对200元以下的文档聚合

    1. GET /hotel/_search
    2. {
    3. "query": {
    4. "range": {
    5. "price": {
    6. "lte": 200
    7. }
    8. }
    9. },
    10. "size": 0,
    11. "aggs": {
    12. "brandAgg": {
    13. "terms": {
    14. "field": "brand",
    15. "size": 20
    16. }
    17. }
    18. }
    19. }

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

    Metric聚合语法

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

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

    1. GET /hotel/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "brandAgg": {
    6. "terms": {
    7. "field": "brand",
    8. "size": 20
    9. },
    10. "aggs": {
    11. "score_stats": {
    12. "stats": {
    13. "field": "score"
    14. }
    15. }
    16. }
    17. }
    18. }
    19. }

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

    1. GET /hotel/_search
    2. {
    3. "size": 0,
    4. "aggs": {
    5. "brandAgg": {
    6. "terms": {
    7. "field": "brand",
    8. "size": 20,
    9. "order": {
    10. "score_stats.avg": "desc"
    11. }
    12. },
    13. "aggs": {
    14. "score_stats": {
    15. "stats": {
    16. "field": "score"
    17. }
    18. }
    19. }
    20. }
    21. }
    22. }

    小结

    aggs代表聚合,与query同级  

    聚合必须的三要素:

    • 聚合名称

    • 聚合类型

    • 聚合字段

    聚合可配置属性有:

    • size:指定聚合结果数量

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

    • field:指定聚合字段

    java代码实现聚合

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

    controller类

    1. import cn.itcast.hotel.pojo.PageResult;
    2. import cn.itcast.hotel.pojo.RequestParams;
    3. import cn.itcast.hotel.service.IHotelService;
    4. import org.springframework.beans.factory.annotation.Autowired;
    5. import org.springframework.web.bind.annotation.PostMapping;
    6. import org.springframework.web.bind.annotation.RequestBody;
    7. import org.springframework.web.bind.annotation.RequestMapping;
    8. import org.springframework.web.bind.annotation.RestController;
    9. import java.util.List;
    10. import java.util.Map;
    11. @RestController
    12. @RequestMapping("/hotel")
    13. public class HotelController {
    14. @Autowired
    15. private IHotelService hotelService;
    16. @PostMapping("filters")
    17. public Map> getFilters(@RequestBody RequestParams params){
    18. return hotelService.getFilters(params);
    19. }
    20. }

    service类

    1. import cn.itcast.hotel.mapper.HotelMapper;
    2. import cn.itcast.hotel.pojo.Hotel;
    3. import cn.itcast.hotel.pojo.HotelDoc;
    4. import cn.itcast.hotel.pojo.PageResult;
    5. import cn.itcast.hotel.pojo.RequestParams;
    6. import cn.itcast.hotel.service.IHotelService;
    7. import com.alibaba.fastjson.JSON;
    8. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    9. import org.elasticsearch.action.search.SearchRequest;
    10. import org.elasticsearch.action.search.SearchResponse;
    11. import org.elasticsearch.client.RequestOptions;
    12. import org.elasticsearch.client.RestHighLevelClient;
    13. import org.elasticsearch.common.geo.GeoPoint;
    14. import org.elasticsearch.common.unit.DistanceUnit;
    15. import org.elasticsearch.index.query.BoolQueryBuilder;
    16. import org.elasticsearch.index.query.QueryBuilders;
    17. import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
    18. import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
    19. import org.elasticsearch.search.SearchHit;
    20. import org.elasticsearch.search.SearchHits;
    21. import org.elasticsearch.search.aggregations.AggregationBuilders;
    22. import org.elasticsearch.search.aggregations.Aggregations;
    23. import org.elasticsearch.search.aggregations.bucket.terms.Terms;
    24. import org.elasticsearch.search.sort.SortBuilders;
    25. import org.elasticsearch.search.sort.SortOrder;
    26. import org.springframework.beans.factory.annotation.Autowired;
    27. import org.springframework.stereotype.Service;
    28. import java.io.IOException;
    29. import java.util.ArrayList;
    30. import java.util.HashMap;
    31. import java.util.List;
    32. import java.util.Map;
    33. @Service
    34. public class HotelService extends ServiceImpl implements IHotelService {
    35. @Autowired
    36. private RestHighLevelClient client;
    37. @Override
    38. public Map> getFilters(RequestParams params) {
    39. try {
    40. // 1.准备Request
    41. SearchRequest request = new SearchRequest("hotel");
    42. // 2.准备DSL
    43. // 2.1.query
    44. // buildBasicQuery(params, request);
    45. // 2.2.设置size
    46. request.source().size(0);
    47. // 2.3.聚合
    48. buildAggregation(request);
    49. // 3.发出请求
    50. SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    51. // 4.解析结果
    52. Map> result = new HashMap<>();
    53. Aggregations aggregations = response.getAggregations();
    54. // 4.1.根据品牌名称,获取品牌结果
    55. List brandList = getAggByName(aggregations, "brandAgg");
    56. result.put("品牌", brandList);
    57. // 4.2.根据品牌名称,获取品牌结果
    58. List cityList = getAggByName(aggregations, "cityAgg");
    59. result.put("城市", cityList);
    60. // 4.3.根据品牌名称,获取品牌结果
    61. List starList = getAggByName(aggregations, "starAgg");
    62. result.put("星级", starList);
    63. return result;
    64. } catch (IOException e) {
    65. throw new RuntimeException(e);
    66. }
    67. }
    68. private void buildAggregation(SearchRequest request) {
    69. request.source().aggregation(AggregationBuilders
    70. .terms("brandAgg")
    71. .field("brand")
    72. .size(100)
    73. );
    74. request.source().aggregation(AggregationBuilders
    75. .terms("cityAgg")
    76. .field("city")
    77. .size(100)
    78. );
    79. request.source().aggregation(AggregationBuilders
    80. .terms("starAgg")
    81. .field("starName")
    82. .size(100)
    83. );
    84. }
    85. private List getAggByName(Aggregations aggregations, String aggName) {
    86. // 4.1.根据聚合名称获取聚合结果
    87. Terms brandTerms = aggregations.get(aggName);
    88. // 4.2.获取buckets
    89. Listextends Terms.Bucket> buckets = brandTerms.getBuckets();
    90. // 4.3.遍历
    91. List brandList = new ArrayList<>();
    92. for (Terms.Bucket bucket : buckets) {
    93. // 4.4.获取key
    94. String key = bucket.getKeyAsString();
    95. brandList.add(key);
    96. }
    97. return brandList;
    98. }
    99. }

    发送请求,获得结果

  • 相关阅读:
    使用MindSpore计算旋转矩阵
    射频微波芯片设计3:射频微波芯片设计基础知识
    麒麟操作系统提示“默认密钥环已上锁”的解决办法
    以入库时间创建分区表
    C++与C编译后符号表对比(一百九十二)
    经典文献阅读之--Online Map Vectorization for Autonomous Driving:(基于栅格化的在线地图矢量化)
    企业如何搭建并运营好积分商城?
    算法竞赛入门【码蹄集进阶塔335题】(MT2276-2280)
    OpenHarmony、HarmonyOS、HarmonyNext互相兼容吗?
    2022杭电多校第二场 1011 DOS Card (线段树)
  • 原文地址:https://blog.csdn.net/qq_63431773/article/details/132685085