Elasticsearch 分布式搜索引擎 -- 数据聚合(聚合的种类、DSL实现聚合、RestAPI实现聚合)
文章目录
- 1. 数据聚合
- 1.1 聚合的种类
- 1.2 DSL实现聚合
- 1.2.1 Bucket聚合语法
- 1.2.2 聚合结果排序
- 1.2.3 限定聚合范围
- 1.2.4 Metric聚合语法
- 1.2.5 小结
- 1.3 RestAPI实现聚合
- 1.3.1 API语法
- 1.3.2 示例代码
- 1.3.3 在lUserService中定义方法,实现对品牌、城市、星级的聚合
本节案例承接上节案例
1. 数据聚合
聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如:
- 什么品牌的手机最受欢迎?
- 这些手机的平均价格、最高价格、最低价格?
- 这些手机每月的销售情况如何?
实现这些统计功能的比数据库的sql
要方便的多,而且查询速度非常快,可以实现近实时搜索效果。
1.1 聚合的种类
小结:
1.2 DSL实现聚合
现在,我们要统计所有数据中的酒店品牌有几种,其实就是按照品牌对数据分组。此时可以根据酒店品牌的名称做聚合,也就是Bucket
聚合。
1.2.1 Bucket聚合语法
语法如下:
GET /hotel/_search
{"size": 0, // 设置size为0,结果中不包含文档,只包含聚合结果"aggs": { // 定义聚合"brandAgg": { //给聚合起个名字"terms": { // 聚合的类型,按照品牌值聚合,所以选择term"field": "brand", // 参与聚合的字段"size": 20 // 希望获取的聚合结果数量}}}
}
结果如图:
1.2.2 聚合结果排序
默认情况下,Bucket聚合会统计Bucket内的文档数量,记为_count,并且按照_count降序排序。
我们可以指定order属性,自定义聚合的排序方式:
GET /hotel/_search
{"size": 0, "aggs": {"brandAgg": {"terms": {"field": "brand","order": {"_count": "asc" // 按照_count升序排列},"size": 20}}}
}
运行结果:
1.2.3 限定聚合范围
默认情况下,Bucket
聚合是对索引库的所有文档做聚合,但真实场景下,用户会输入搜索条件,因此聚合必须是对搜索结果聚合。那么聚合必须添加限定条件。
我们可以限定要聚合的文档范围,只要添加query
条件即可:
GET /hotel/_search
{"query": {"range": {"price": {"lte": 200 // 只对200元及以下的文档聚合}}}, "size": 0, "aggs": {"brandAgg": {"terms": {"field": "brand","size": 20}}}
}
这次,聚合得到的品牌明显变少了:
1.2.4 Metric聚合语法
上面,我们对酒店按照品牌分组,形成了一个个桶。现在我们需要对桶内的酒店做运算,获取每个品牌的用户评分的min
、max
、avg
等值。
这就要用到Metric
聚合了,例如stats
聚合:就可以获取min
、max
、avg
等结果。
语法如下:
GET /hotel/_search
{"size": 0, "aggs": {"brandAgg": { "terms": { "field": "brand", "size": 20},"aggs": { // 是brands聚合的子聚合,也就是分组后对每组分别计算"scoreAgg": { // 聚合名称"stats": { // 聚合类型,这里stats可以计算min、max、avg等"field": "score" // 聚合字段,这里是score}}}}}
}
这次的score_stats
聚合是在brandAgg
的聚合内部嵌套的子聚合。因为我们需要在每个桶分别计算。
运行结果:
另外,我们还可以给聚合结果做个排序,例如按照每个桶的酒店平均分做排序:
1.2.5 小结
1.3 RestAPI实现聚合
1.3.1 API语法
聚合条件与query
条件同级别,因此需要使用request.source()
来指定聚合条件。
聚合条件的语法:
聚合的结果也与查询结果不同,API
也比较特殊。不过同样是JSON
逐层解析:
1.3.2 示例代码
HotelAggregationTest.java
package cn.itcast.hotel;import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import java.io.IOException;
import java.util.List;@SpringBootTest
class HotelAggregationTest {private RestHighLevelClient client;@Testvoid testAgg() throws IOException {// 1.准备请求SearchRequest request = new SearchRequest("hotel");// 2.请求参数// 2.1.sizerequest.source().size(0);// 2.2.聚合request.source().aggregation(AggregationBuilders.terms("brandAgg").field("brand").size(20));// 3.发出请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析结果Aggregations aggregations = response.getAggregations();// 4.1.根据聚合名称,获取聚合结果Terms brandAgg = aggregations.get("brandAgg");// 4.2.获取bucketsList<? extends Terms.Bucket> buckets = brandAgg.getBuckets();// 4.3.遍历for (Terms.Bucket bucket : buckets) {String brandName = bucket.getKeyAsString();System.out.println("brandName = " + brandName);long docCount = bucket.getDocCount();System.out.println("docCount = " + docCount);}}@BeforeEachvoid setUp() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.135.130:9200")));}@AfterEachvoid tearDown() throws IOException {client.close();}
}
运行结果:
1.3.3 在lUserService中定义方法,实现对品牌、城市、星级的聚合
返回值类型就是页面要展示的最终结果:
结果是一个Map
结构:
key
是字符串,城市、星级、品牌、价格value
是集合,例如多个城市的名称
业务实现:
在cn.itcast.hotel.web
包的HotelController
中添加一个方法,遵循下面的要求:
- 请求方式:
POST
- 请求路径:
/hotel/filters
- 请求参数:
RequestParams
,与搜索文档的参数一致 - 返回值类型:
Map<String, List<String>>
代码:
@PostMapping("/filters")public Map<String, List<String>> getFilters(@RequestBody RequestParams params){return hotelService.getFilters(params);}
这里调用了IHotelService
中的getFilters
方法,尚未实现。
在cn.itcast.hotel.service.IHotelService
中定义新方法:
Map<String, List<String>> getFilters(RequestParams params);
在cn.itcast.hotel.service.impl.HotelService
中实现该方法:
@Overridepublic Map<String, List<String>> getFilters(RequestParams params) {try {// 1.准备RequestSearchRequest request = new SearchRequest("hotel");// 2.准备DSL// 2.1.querybuildBasicQuery(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;}
运行结果(需要重启项目):
{"品牌":["7天酒店","如家","皇冠假日","速8","万怡","华美达","和颐","万豪","喜来登","希尔顿","汉庭","凯悦","维也纳","豪生","君悦","万丽","丽笙"],"星级":["二钻","五钻","四钻","五星级","三钻","四星级"],"城市":["上海","北京","深圳"]
}
Elasticsearch 分布式搜索引擎 -- 数据聚合(聚合的种类、DSL实现聚合、RestAPI实现聚合)相关推荐
- Elasticsearch——分布式搜索引擎01(索引库、文档、RestAPI、RestClient、拼音分词器、IK分词器)
Elasticsearch--分布式搜索引擎01(索引库.文档.RestAPI.RestClient.拼音分词器.IK分词器) 一.初识 elesticsearch 1.1 简介 1.2 倒排索引(重 ...
- Elasticsearch 分布式搜索引擎 -- 数据同步:数据同步思路分析 实现elasticsearch与数据库数据同步
文章目录 1. 数据同步思路分析 1.1 同步调用 1.2 异步通知 1.3 监听binlog 1.4 小结 2. 实现数据同步 2.1 导入hotel-admin 2.2 声明交换机.队列 1)引入 ...
- ElasticSearch分布式搜索引擎从入门到实战应用(入门篇-基本命令操作)
ElasticSearch分布式搜索引擎从入门到实战应用(入门篇) 1.入门须知 2.ElasticSearch概述 2.1.ES简介 2.2.应用场景 3.ES和Solr的对比 3.1.ES作用 3 ...
- 爬梯:ElasticSearch分布式搜索引擎
学习资料:狂神说 ElactisSearch 7.6.2 ElasticSearch 分布式搜索引擎 1. 概述 1.1 ELK ELK是ElasticSearch.Logstash.Kibana三大 ...
- ElasticSearch分布式搜索引擎——从入门到精通
ES分布式搜索引擎 注意: 在没有创建库的时候搜索,ES会创建一个库并自动创建该字段并且设置为String类型也就是text 什么是elasticsearch? 一个开源的分布式搜索引擎,可以用来实现 ...
- elasticsearch分布式搜索引擎详细使用总结
文章目录 一.初识elasticsearch 1.1.ES了解 1.1.1.elasticsearch的作用 1.1.2.ELK技术栈 1.1.3.elasticsearch和lucene 1.1.4 ...
- ElasticSearch分布式搜索引擎-03
1.数据聚合 聚合可以让我们极其方便的实现对数据的统计.分析.运算.查询速度非常快,可以实现近实时搜索效果 1.1.聚合的种类 聚合常见的有三类: 桶(Bucket)聚合:用来对文档做分组 TermA ...
- 大数据(二)Elasticsearch 分布式搜索引擎(存索引、索引搜索)
一.Elasticsearch 存索引, Hbase 里存原数据 例如:一条告警上报过来,会同时存Hbase, ES里,Hbase存原数据,ES里只存索引(包含告警ID, 告警级别,告警状态,告警时间 ...
- 项目1在线交流平台-6.Elasticsearch分布式搜索引擎-3.ES结合Kafka应用-开发社区搜索功能
文章目录 功能需求 一.Service层处理操作ES服务器的数据 二.Controller层处理帖子添加和评论事件请求 1.添加帖子时-触发事件-发布消息 2. 添加评论时-触发发帖事件-发布消息 三 ...
- Elasticsearch 分布式搜索引擎 -- 自动补全(拼音分词器、自定义分词器、自动补全查询、实现搜索框自动补全)
文章目录 1. 自动补全 1.1 拼音分词器 1.2.1 自定义分词器 1.2.2 小结 1.2 自动补全 1.3 实现酒店搜索框自动补全 1.3.1 修改酒店映射结构 1.3.2 修改HotelDo ...
最新文章
- php中getdistance函数_php计算两个经纬度地点之间的距离
- [LeetCode] Maximum Subarray 最大子数组
- injectionForXcode代码注入步骤
- 用户空间增加、缩减内存
- OpenYurt 如何 “0 侵入” 攻破云边融合难点
- Windows 7 完美安装 Visual C++ 6.0
- java的传值调用什么_Java的传值调用
- 网络编程的4种IO模型
- 第二节:Css重写样式
- php 将前端网页输出成unicdoe编码
- 日记 [2008年03月23日]不编译内核给iptables增加模块
- logisim输出变成红色的e_新款E刚出就被骂最丑,却销量可观,梅赛德斯:都是小事儿,上AMG...
- 使用 Repeater方式和完全静态页面使用AJAX读取和提交数据
- bootstrap 树
- 用计算机弹出古诗,电脑屏保不断变化的诗句
- 当你一个人走过你们曾经走过的大街小巷,你会有何感受?
- 处理 JS中 undefined 的7个技巧
- 十年之前..., 十年之后...
- ue4 无限地图_基于UE4的开放世界地图架构
- nsf5隐写算法 matlab,基于纹理复杂度的JPEG图像自适应隐写