目录:
(1)数据聚合-聚合的分类
(2)数据聚合-DSL实现Bucket聚合
(3) 数据聚合-DSL实现Metrics聚合
(4)数据聚合-RestClient实现聚合
(5)数据聚合-多条件聚合
(6)数据聚合-带过滤条件的聚合
前面学习了ES的基本用法和数据搜索功能,下面 继续深入ES的搜索功能,看一看它更复杂的用法
数据聚合:可以帮助我们可以对海量的数据做统计分析,如果结合Kanban形成可视化的报表,让用户一目了然形成数据结果,更方便数据分析
自动补全:可以根据用户输入的部分信息,去自动补全和提示用户想要输入的内容 ,增加用户的体验
数据同步:ES和MySQL数据库的双写的一致性问题,对应的解决方案
(1)数据聚合-聚合的分类
在MySQL也有聚合功能:聚合函数:avg、max、min等等,聚合函数需要结合group by分组去使用
ES具备MySQL类似的聚合功能,并且还做了更丰富的聚合功能:
聚合先学习下面常见的,详细可以查看官网:
Aggregations | Elasticsearch Guide [8.6] | Elastic
桶聚合:类似Group by
(2)数据聚合-DSL实现Bucket聚合
aggs:aggressions的缩写,aggs里面可以定义好多的聚合的,所以是一个数组,里面可以定义多个
定义几个brandAgg就会有多少个brandAgg 的结果
size=0 是搜索中不包含文档,所以hits是空的
关注的是aggregations
buckets是桶:聚合是桶的聚合,所以结果有很多桶,这个桶是品牌的桶,品牌一样的放在一个桶里面,所以是一个数组,会有很多桶
里面的size是显示10条
doc_count:是文档数量,桶里面有几条文档啊,是倒叙排序,统计出来越多的排名越靠前,这是默认的排序规则,排序可以更改
上面的聚合是对整个索引库的搜索,如果有上亿条数据,这个聚合对内存的消耗还是非常大的 ,我们能不能限定聚合搜索的范围呢?
(3) 数据聚合-DSL实现Metrics聚合
在按照平均评分做降序排列:
(4)数据聚合-RestClient实现聚合
添加一个单元测试方法:
添加解析:
(5)数据聚合-多条件聚合
在IHotelService中定义新的接口:
实现类IHotelServiceImpl中实现这个方法:
可以把聚合条件封装成一个方法Ctrl+Alt+M
把解析方法中相同的部分也进行封装成一个方法Ctrl+Alt+M
解析封装的方法:
封装的聚合方法:
最终代码:
在一个测试类中打印一下这个结果:
成功的得到了三个字段的聚合结果:
(6)数据聚合-带过滤条件的聚合
filter:是查询聚合过滤项的请求
发现这两个请求携带的参数是一样的,为什么查过滤项的时候也要带条件呢?过滤项查询要通过聚合来实现,聚合一带上条件就来限定聚合的范围,为何要限定范围呢?直接对整个索引库做聚合不行呢?
在搜索是没有加条件,搜索的是索引库的所有数据,对所有数据做聚合得到城市和品牌没有问题,但是当输入内容虹桥,得到的数据一定是跟上海虹桥有关的结果
上海虹桥有关的城市对应的一定是上海,但是对索引库的所有数据做聚合,得到的城市一定包含所有的城市,所以用户一定就很奇怪拉,命名搜索的是上海的还能出现北京的呢?如果再点击北京在结合搜索条件虹桥,能搜到任何东西吗?肯定是不能的北京没有虹桥,所以说不应该对索引库的所有字段做聚合,用户条件是虹桥,就应该对虹桥相关的酒店做聚合,限定聚合的范围,需要加查询条件,查询时用什么条件聚合时也用什么条件,这样就是在酒店的基础上做聚合,这样查询结果就更精确了因此,在查询过滤项时和查询时要用相同的条件
在HotelController中添加新的接口访问:
修改接口的方法:加上一个参数,上面已经写过这个方法,只是没有参数
实现类的方法:加一个参数,加一个查询条件
聚合封装的方法buildAggregation()
封装的聚合方法:
query封装的过滤方法:
发现已经搜索出来了:
使用价格过滤:城市变少了
在添加搜索虹桥:搜到的更少了,城市直接就没了,因为虹桥只有是上海,没有必要在去选
所以在聚合的时候需要添加一些过滤条件,去限制聚合的范围。