详解SpringCloud微服务技术栈:深入ElasticSearch(1)——数据聚合

news2024/11/13 15:13:44

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
🌌上期文章:详解SpringCloud微服务技术栈:ElasticSearch实战(旅游类项目)
📚订阅专栏:微服务技术全家桶
希望文章对你们有所帮助

在之前已经了解了ElasticSearch的基本用法(DSL语句以及RestClient实现),并利用ElasticSearch做了一个旅游类项目加以巩固,现在要进行ElasticSearch更深入的内容,内容包括:

数据聚合:来对海量数据做统计和分析,结合kibana还能形成可视化的图形报表
自动补全:根据用户输入的部分关键字信息去补全关键字
数据同步:先分析MySQL与ElasticSearch的双写一致性问题,并给出对应的解决方案
集群:ES的集群和集群中不同角色的作用,并且搭建一个企业级的高可用的集群

深入ElasticSearch——数据聚合

  • 数据聚合
    • 聚合分类
    • DSL实现Bucket聚合
    • DSL实现Metrics聚合
    • RestClient实现聚合
    • 多条件聚合
    • 带过滤条件的聚合

数据聚合

聚合分类

聚合可以实现对文档数据的统计、分析和运算。常见聚合有3类:
在这里插入图片描述

DSL实现Bucket聚合

现在要统计所有数据中的酒店品牌有几种,此时可以根据酒店品牌的名称做聚合。
MySQL里面直接用group by,而这里需要用Bucket聚合,具体来说是用的term聚合:

# 对价格小于200的做聚合,也可以不限定聚合的范围(不写query)
GET /hotel/_search
{
	"query": {
		"range": {
			"price": {
				"lte": 200
			}
		}
	},
	"size": 0, # 设置size=0,表示结果中不包含文档,只包含聚合结果
	"aggs": { # 定义聚合
		"brandAgg": { # 给聚合起个名字
			"terms": { # 聚合的类型,按照品牌,因此选择term
				"field": "brand", # 参与聚合的字段
				"size": 20 # 希望获取的聚合结果的数量,默认10
			}
		}
	}
}

DSL实现Metrics聚合

获取每个品牌的用户评分的min、max、avg等值,因此要做聚合的嵌套,在每个bucket中做计算:

GET /hotel/_search
{
	"size": 0,
	"aggs": {
		"brandAgg": {
			"terms": {
				"field": "brand",
				"size": 20,
				"order": { # 做排序,需要指定排序的字段
				  "scoreAgg.avg": "desc"
				}
			},
			"aggs": { # 品牌聚合的自聚合,对每组分别做计算
			  "scoreAgg": { # 聚合名称
			    "stats": { # 聚合类型,stats可以计算min、max、avg
			      "field": "score" # 聚合字段
			    }
			  }
			}
		}
	}
}

RestClient实现聚合

依然是通过DSL语句来写java语句:
在这里插入图片描述
编写测试类:

	@Test
    void testAggregation() throws IOException {
        //1.准备request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        //2.1 设置size,不需要查看文档,只要看聚合结果
        request.source().size(0);
        //2.1 聚合
        request.source().aggregation(AggregationBuilders
                .terms("brandAgg") //聚合名称"brandAgg",类型terms
                .field("brand") //参与聚合的字段
                .size(10)
        );
        //3.发出请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //打印即可查看输出的结构,对照结构来做逐层做解析
        //System.out.println("response = " + response);
        //4.解析结果
        //4.1 获取聚合信息
        Aggregations aggregations = response.getAggregations();
        //4.2根据聚合名称获取聚合结果(之前是term类型这里返回的也是term类型)
        Terms brandTerms = aggregations.get("brandAgg");
        //4.3获取buckets
        List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
        //4.4遍历buckets,取出每一个桶(分类)
        for (Terms.Bucket bucket : buckets) {
            String key = bucket.getKeyAsString();
            System.out.println("key = " + key);
        }
    }

在这里插入图片描述

多条件聚合

在IUserService接口中定义方法,实现对品牌、城市、星级的聚合(搜索页面的品牌、城市等信息不应该是在页面中写死的,而是通过聚合索引库中的酒店数据得来的)。

例如,我限定了价格的range为100-300,如果杭州不包含这样价位的酒店,那么导航栏上面的城市信息直接就不应该有杭州两个字

IUserService中声明方法:

	/**
     * 查询城市、星级、品牌的聚合效果
     * @return 聚合结果,格式:{"城市": {"上海", "北京"}, "品牌": {"如家", "希尔顿"}}
     */
    Map<String, List<String>> filters();

UserService实现方法体:

	@Override
    public Map<String, List<String>> filters() {
        try {
            //1.准备request
            SearchRequest request = new SearchRequest("hotel");
            //2.准备DSL
            //2.1设置size
            request.source().size(0);
            //2.2设置聚合
            buildAggregation(request);
            //3.发出请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            //4.解析响应
            Map<String, List<String>> result = new HashMap<>(); //存放解析后的结果
            Aggregations aggregations = response.getAggregations();
            result.put("brand", getAggByName(aggregations, "brandAgg"));
            result.put("city", getAggByName(aggregations, "cityAgg"));
            result.put("starName", getAggByName(aggregations, "starAgg"));
            return result;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private List<String> getAggByName(Aggregations aggregations, String aggName) {
        List<String> list = new ArrayList<>(); //存放每个桶的value
        Terms brandTerms = aggregations.get(aggName); //这里返回值不要默认,自行设置为Terms类型的
        List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
        for (Terms.Bucket bucket : buckets) {
            String key = bucket.getKeyAsString();
            list.add(key);
        }
        return list;
    }

    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)
        );
    }

可以在测试类中注入IUserService,调用方法查看运行结果:

	@Resource
    private IHotelService hotelService;

    @Test
    void contextLoads() {
        Map<String, List<String>> filters = hotelService.filters();
        System.out.println("filters = " + filters);
    }

在这里插入图片描述

带过滤条件的聚合

聚合已经完成,但是聚合的结果还没有返回到前端,实际上前端页面会向服务端发起请求,查询品牌、城市、星级等字段的聚合结果,我们应当渲染完返还给前端。

查看前端的请求:
在这里插入图片描述
可以看到请求的参数和之前的list里面的是一样,这是因为需要限定一下范围,比如限定了城市为北京,搜索条件为“如家”,那么应该对北京的、名字带“如家”的酒店去做聚合,而不是所有的酒店,这样会大大提高效率。

1、编写controller接口,接受该请求

	@PostMapping("/filters")
    public Map<String, List<String>> getFilters(@RequestBody RequestParams params){
        return hotelService.filters(params);
    }

2、修改IUserService#getFilter()方法,添加RequestParam参数

Map<String, List<String>> filters(RequestParams params);

3、修改getFilters方法的业务,聚合时添加query条件
在这里插入图片描述
至此,数据聚合的实现已经完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1421826.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【RT-DETR改进涨点】ResNet18、34、50、101等多个版本移植到ultralytics仓库(RT-DETR官方一比一移植)

👑欢迎大家订阅本专栏,一起学习RT-DETR👑 一、本文介绍 本文是本专栏的第一篇改进,我将RT-DETR官方版本中的ResNet18、ResNet34、ResNet50、ResNet101移植到ultralytics仓库,网上很多改进机制是将基础版本的也就是2015年发布的ResNet移植到ultralytics仓库中,但是其实…

【Emgu CV教程】6.6、图像平滑之GaussianBlur()高斯滤波

文章目录 一、介绍1.原理2.函数介绍 二、举例1.原始素材2.代码3.运行结果 一、介绍 1.原理 高斯滤波是Emgu CV里面最常用的滤波&#xff0c;因为它在平滑图像的同时&#xff0c;可以更好的保留轮廓和边缘信息。下面这段来自百度百科的介绍&#xff1a; 高斯滤波是一种线性平滑…

思腾合力深思系列「IW4230-4GR」可扩展处理器的多场景适配服务器

思腾合力深思系列IW4230-4GR&#xff0c;采用第四代Intel Xeon Eagle Stream可扩展处理器的多场景适配服务器&#xff0c;支持4张双宽GPU卡。 思腾合力深思系列IW4230-4GR GPU服务器/工作站支持双路第四代IntelXeon Eagle Stream系列可扩展处理器&#xff0c;具有高性能、高密度…

【史上最全的接口与抽象类】

Java异常处理与try-catch-finally 抽象类和接口是Java中用于实现抽象和多态的关键概念。 抽象类的定义和语法&#xff1a;接口的定义和语法&#xff1a;接口和抽象类的区别主要在以下几个方面&#xff1a; 抽象类和接口是Java中用于实现抽象和多态的关键概念。 抽象类的定义和…

【Java异常处理与try-catch-finally】

Java异常处理与try-catch-finally try块是被监视的代码块&#xff0c;可能会发生异常的地方。当try块中的代码抛出了异常&#xff0c;程序会立即转入catch块&#xff0c;catch块根据捕获的异常类型进行处理。 Java异常处理是一种机制&#xff0c;用于捕获并处理在程序执行过程中…

用GPT写PHP框架

参考https://www.askchat.ai?r237422 写一个mvc框架 上面是简单的案例&#xff0c;完整的PHP框架&#xff0c;其核心通常包含以下几个关键组件&#xff1a; 1. 路由&#xff08;Routing&#xff09;&#xff1a;路由组件负责解析请求的URL&#xff0c;并将其映射到相应的控制…

CAD-autolisp(四)——编译

目录 一、编译1.1 界面操作1.2 生成的应用程序&#xff08;二选一&#xff09; 二、后续学习 一、编译 编译&#xff1a;lsp后缀名为原文件&#xff0c;后缀名为fas、vlx为编译后文件&#xff0c;其会把sld、dcl、lsp等文件都编译进一个应用程序文件中加载&#xff1a;cad命令…

写作业考试用ChatGPT,留学如何防范“学术不端”危机?

近日&#xff0c;哈佛校长克洛迪娜盖伊在校园“反犹风波”中因立场问题被迫辞职。此外&#xff0c;哈佛大学相关调查委员会还发现盖伊在学术论文中存在错误引用资料来源等问题。对于种种学术不端行为&#xff0c;留学生如何防范&#xff1f;在ChatGPT时代&#xff0c;出国留学如…

C++ 数论相关题目,博弈论,SG函数,集合-Nim游戏

给定 n 堆石子以及一个由 k 个不同正整数构成的数字集合 S 。 现在有两位玩家轮流操作&#xff0c;每次操作可以从任意一堆石子中拿取石子&#xff0c;每次拿取的石子数量必须包含于集合 S &#xff0c;最后无法进行操作的人视为失败。 问如果两人都采用最优策略&#xff0c;…

保护医疗数据不受威胁:MPLS专线在医疗网络安全中的角色

随着数字技术的快速发展&#xff0c;医疗行业正在经历一场革命。从电子健康记录到远程医疗服务&#xff0c;数字化不仅提高了效率&#xff0c;也带来了前所未有的挑战--尤其是关于数据安全和隐私保护的挑战。在这样的背景下&#xff0c;如何确保敏感的医疗数据安全传输&#xf…

Qt6入门教程 14:QToolButton

目录 一.简介 二.常用接口 1.void setMenu(QMenu * menu) 2.void setPopupMode(ToolButtonPopupMode mode) 3.void setToolButtonStyle(Qt::ToolButtonStyle style) 4.void setArrowType(Qt::ArrowType type) 5.void setDefaultAction(QAction * action) 三.实战演练 1…

C/C++ (stdio.h)标准库详解

cstdio,在C语言中称为stdio.h。该库使用所谓的流与物理设备&#xff08;如键盘、打印机、终端&#xff09;或系统支持的任何其他类型的文件一起操作。 在本文将会通过介绍函数参数&#xff0c;举出实际的简单例子来帮助大家快速上手使用函数。 目录 一、流 二、库函数 1、F…

Zerosync:构建基于STARK的Bitcoin证明系统

1. 引言 前序博客&#xff1a; BitcoinSTARK: ZeroSync & Khepri Robin Linus、Tino Steffens、Lukas George 等人成立了一个名为 ZeroSync 协会&#xff08;ZeroSync Association&#xff09;的瑞士非营利组织&#xff0c;该组织将牵头开发比特币证明系统。ZeroSync 于…

STM32——ADC

STM32——ADC 1.ADC介绍 ADC是什么&#xff1f; 全称&#xff1a;Analog-to-Digital Converter&#xff0c;指模拟/数字转换器! ADC性能指标 量程&#xff1a;能测量的电压范围分辨率&#xff1a;ADC能辨别的最小模拟量&#xff0c;通常以输出二进制数的位数表示&#xf…

春季选品策略:如何在Shopee平台上脱颖而出

在Shopee平台上进行春季选品时&#xff0c;卖家需要制定有效的策略来吸引消费者的注意并提高销售业绩。本文将介绍一些关键的选品策略&#xff0c;帮助卖家在春季市场中脱颖而出。 先给大家推荐一款shopee知虾数据运营工具知虾免费体验地址&#xff08;复制浏览器打开&#xf…

嵌入式——模拟/数字转换器(ADC)补充

目录 一、ADC简介 二、ADC功能 1.电压输入范围 2.输入通道 3. 转换顺序 &#xff08;1&#xff09;规则序列 &#xff08;2&#xff09; 注入序列 4.触发源 5. 转换时间 &#xff08;1&#xff09; ADC时钟 &#xff08;2&#xff09; 采样时间 6. 数据寄存器 &am…

回归预测 | Matlab实现CPO-BiLSTM【24年新算法】冠豪猪优化双向长短期记忆神经网络多变量回归预测

回归预测 | Matlab实现CPO-BiLSTM【24年新算法】冠豪猪优化双向长短期记忆神经网络多变量回归预测 目录 回归预测 | Matlab实现CPO-BiLSTM【24年新算法】冠豪猪优化双向长短期记忆神经网络多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现CPO-B…

字符串中的单词反转【leetcode】

本题选自leetcode图解算法数据结构一书 你在与一位习惯从右往左阅读的朋友发消息&#xff0c;他发出的文字顺序都与正常相反但单词内容正确&#xff0c;为了和他顺利交流你决定写一个转换程序&#xff0c;把他所发的消息 message 转换为正常语序。 注意&#xff1a;输入字符串…

python 标准库random生成随机数

当前版本&#xff1a; Python 3.8.4 文章目录如下 1. random的特点 2. random的用法 2.1. 随机整数 2.2. 随机小数 2.3. 随机元素 2.4. 随机字符串 1. random的特点 random 提供了生成伪随机数的功能&#xff0c;可以用于各种随机相关的操作&#xff0c;如生成随机数、…

LVS常用的NAT模式和DR模式实战示例

引言&#xff1a;紧接上文&#xff0c;了解LVS&#xff0c;这一篇就够了-CSDN博客&#xff0c;今天我们对LVS常用的两种模式来进行示例配置演示 LVS-NAT模式 1、环境准备 准备 3 台纯净的虚拟机 关闭防火墙和selinux 例&#xff1a; lvs-server 添加两个网卡 NAT模式 …