文章目录
- 一 DWS层-关键词主题表(FlinkSQL)
- 1 过滤数据
- 2 利用UDTF进行拆分
- (1)拆分结果
- (2)Join 表函数 (UDTF)
- (3)代码
- 3 分组、开窗、聚合计算
- 4 转换为流并写入ClickHouse
- (1)在ClickHouse中创建关键词统计表
- (2)封装KeywordStats实体类
- (3)在主程序中转换流并写入ClickHouse
- 5 整体测试
- 二 数据可视化接口
- 1 设计思路
- 2 需求梳理
- (1)效果图
- (2)分析可视化大屏
- (3)接口执行过程
- 三 Sugar数据大屏
- 1 产品介绍
- 2 使用入口
- 3 创建数据大屏
- 四 总成交金额接口
- 1 Sugar组件:数字翻牌器
- (1)添加组件
- (3)查询组件需要的数据格式
- (4)接口访问路径以及返回格式
- 1.1.4 接口访问路径以及返回格式
- (5)执行SQL
- a product_stats_2022表中数据
- b product_stats_2022表结构
- c SQL语句
- 2 数据接口实现
- (1)创建数据接口模块
- a 在gmall2022-parent项目下创建新的SpringBoot模块gmall2022-publisher
- b 在pom.xml文件中添加需要的依赖
- (2)代码分层结构
- a 代码结构
- b 修改Springboot核心配置文件 application.properties
- c 创建包结构
- (3)代码分层实现
- a Mapper层:创建ProductStatsMapper接口
- b 在Application中添加@MapperScan的注解
- c Service层:创建ProductStatsService接口
- d Service层:创建ProductStatsServiceImpl实现类
- e Controller层:创建SugarController类
- (4)测试本地接口
- a 启动SpringBoot应用程序
- b 输出结果
一 DWS层-关键词主题表(FlinkSQL)
1 过滤数据
// TODO 4 将动态表中表示搜索行为的记录过滤出来
Table fullwordTable = tableEnv.sqlQuery("select " +
" page['item'] fullword,rowtime " +
" from " +
" page_view " +
" where " +
" page['page_id']='good_list' and page['item'] is not null");
2 利用UDTF进行拆分
(1)拆分结果
搜索内容:荣耀Play6T Pro 天玑810
fullword rowtime
荣耀Play6T Pro 天玑810 20221215
拆分后的效果:荣耀 Play6T Pro 天玑 810
keyword rowtime
荣耀 20221215
Play6T 20221215
Pro 20221215
天玑 20221215
810 20221215
(2)Join 表函数 (UDTF)
将表与表函数的结果进行 join 操作。左表(outer)中的每一行将会与调用表函数所产生的所有结果中相关联行进行 join 。
用户自定义表函数( User-defined table functions,UDTFs ) 在执行前必须先注册。请参考 UDF 文档 以获取更多关于指定和注册UDF的信息
(3)代码
// TODO 2 注册自定义UDTF函数
tableEnv.createTemporarySystemFunction("ik_analyze", KeywordUDTF.class);
// TODO 5 使用自定义UDTF函数对搜索关键词进行拆分
Table keywordTable = tableEnv.sqlQuery("SELECT rowtime, keyword FROM "+ fullwordTable +", LATERAL TABLE(ik_analyze(fullword)) AS T(keyword)");
3 分组、开窗、聚合计算
// TODO 6 分组、开窗、聚合计算
Table resTable = tableEnv.sqlQuery("select " +
" DATE_FORMAT(TUMBLE_START(rowtime, INTERVAL '10' SECOND),'yyyy-MM-dd HH:mm:ss') as stt, " +
" DATE_FORMAT(TUMBLE_END(rowtime, INTERVAL '10' SECOND),'yyyy-MM-dd HH:mm:ss') as edt, " +
" keyword, " +
" count(*) ct," +
" '"+ GmallConstant.KEYWORD_SEARCH +"' source," +
" UNIX_TIMESTAMP() * 1000 as ts" +
" from " +
" "+ keywordTable +" " +
" group by " +
" TUMBLE(rowtime, INTERVAL '10' SECOND),keyword ");
4 转换为流并写入ClickHouse
(1)在ClickHouse中创建关键词统计表
create table keyword_stats_2022 (
stt DateTime,
edt DateTime,
keyword String ,
source String ,
ct UInt64 ,
ts UInt64
)engine =ReplacingMergeTree( ts)
partition by toYYYYMMDD(stt)
order by ( stt,edt,keyword,source );
(2)封装KeywordStats实体类
package com.hzy.gmall.realtime.beans;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Desc: 关键词统计实体类
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class KeywordStats {
private String keyword;
private Long ct;
private String source;
private String stt;
private String edt;
private Long ts;
}
(3)在主程序中转换流并写入ClickHouse
// TODO 7 将表转换为流
DataStream<KeywordStats> keywordStatsDS = tableEnv.toAppendStream(resTable, KeywordStats.class);
keywordStatsDS.print(">>>");
// TODO 8 将流中数据写入ck中
keywordStatsDS.addSink(ClickhouseUtil.getJdbcSink(
// 字段顺序与实体类中属性顺序要一致
"insert into keyword_stats_2022(keyword,ct,source,stt,edt,ts) values(?,?,?,?,?,?) "
));
5 整体测试
- 启动ZK、Kafka、logger.sh、ClickHouse
- 运行BaseLogApp
- 运行KeywordStatsApp
- 运行rt_applog目录下的jar包
- 查看控制台输出
- 查看ClickHouse中keyword_stats_2022表数据
二 数据可视化接口
1 设计思路
之前数据分层处理,最后把轻度聚合的结果保存到ClickHouse中,主要的目的就是提供即时的数据查询、统计、分析服务。这些统计服务一般会用两种形式展现,一种是为专业的数据分析人员的BI工具,一种是面向非专业人员的更加直观的数据大屏。
以下主要是面向百度的sugar的数据大屏服务的接口开发。
2 需求梳理
(1)效果图
(2)分析可视化大屏
在可视化大屏中每个组件都需要一个单独的接口,图中一共涉及8个组件。
组件名称 | 组件 | 查询指标 | 对应的数据表 |
---|---|---|---|
总成交金额 | 数字翻牌 | 订单总金额 | product_stats |
省市热力图查询 | 热力图 | 省市分组订单金额 | province_stats |
分时流量 | 折线图 | UV分时数 PV分时数 新用户分时数 | visitor_stats |
品牌TopN | 水平柱状图 | 按品牌分组订单金额 | product_stats |
品类分布 | 饼状图 | 按品类分组订单金额 | product_stats |
热词字符云 | 字符云 | 关键词分组计数 | keyword_stats |
流量表格 | 交叉透视表 | UV数(新老用户) PV数(新老用户) 跳出率(新老用户) 平均访问时长 (新老用户) 平均访问页面数(新老用户) | visitor_stats |
热门商品 | 轮播表格 | 按SPU分组订单金额 | product_stats |
(3)接口执行过程
之前实现了DWS层计算后写入到ClickHouse中,接下来就是要为可视化大屏服务,提供一个数据接口用来查询ClickHouse中的数据。这里主要有两项工作
- 配置可视化大屏服务。
- 编写数据查询接口以供可视化大屏进行访问。
三 Sugar数据大屏
1 产品介绍
Sugar是百度云推出的敏捷 BI 和数据可视化平台,目标是解决报表和大屏的数据 BI 分析和可视化问题,解放数据可视化系统的开发人力。
2 使用入口
https://cloud.baidu.com/product/sugar.html
3 创建数据大屏
-
点击【立即使用】后,登录百度账号
-
首先创建组织
-
创建中选择产品【大屏尝鲜版】,首次使用有一个月的试用期
-
新建好组织后选择【进入组织】
-
然后进入默认的【第一个空间】
-
在空间中选择【待创建大屏】后的【新建】
-
选择大屏的模板
-
可以选空模板,也可以根据现有的模板进行修改
(8) 可以选空模板,也可以根据现有的模板进行修改
- 这里选择空白模板,并指定大屏的名称
- 进入大屏的编辑窗口
四 总成交金额接口
1 Sugar组件:数字翻牌器
(1)添加组件
从大屏的编辑器上方选择【指标】→【数字翻牌器】
(3)查询组件需要的数据格式
在数据绑定的位置选择【静态JSON】,可以看到数据需要的JSON格式
(4)接口访问路径以及返回格式
1.1.4 接口访问路径以及返回格式
- 访问路径:/api/sugar/gmv
- 返回格式
{
"status": 0,
"data": 1201012.694507823
}
(5)执行SQL
a product_stats_2022表中数据
b product_stats_2022表结构
c SQL语句
toYYYYMMDD:将Date或DateTime转换为包含年份和月份编号的UInt32类型的数字(YYYY * 10000 + MM * 100 + DD)。
select sum(order_amount) order_amount from product_stats_2022 where toYYYYMMDD(stt)=20221215;
2 数据接口实现
(1)创建数据接口模块
a 在gmall2022-parent项目下创建新的SpringBoot模块gmall2022-publisher
可以先不选择依赖,之后统一在pom.xml中添加
b 在pom.xml文件中添加需要的依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.hzy.gmall.publisher</groupId>
<artifactId>gmall2022-publisher</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gmall2022-publisher</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>ru.yandex.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>0.1.55</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
(2)代码分层结构
a 代码结构
分层 | 类 | 处理内容 |
---|---|---|
controller 控制层 | SugarController | 查询交易额接口及返回参数处理 |
service 服务层 | ProductStatsService ProductStatsServiceImpl | 查询商品统计数据 |
mapper 数据映射层 | ProductStatsMapper | 编写SQL查询商品统计表 |
b 修改Springboot核心配置文件 application.properties
server.port=8070
#配置ClickHouse驱动以及URL
spring.datasource.driver-class-name=ru.yandex.clickhouse.ClickHouseDriver
spring.datasource.url=jdbc:clickhouse://hadoop101:8123/default
c 创建包结构
(3)代码分层实现
a Mapper层:创建ProductStatsMapper接口
package com.hzy.gmall.publisher.mapper;
/**
* 商品统计Mapper接口
*/
public interface ProductStatsMapper {
// 获取某天商品的总交易额
@Select("select sum(order_amount) order_amount from product_stats_2022 where toYYYYMMDD(stt)=#{date}")
BigDecimal selectGMV(Integer date);
}
b 在Application中添加@MapperScan的注解
package com.hzy.gmall.publisher;
@SpringBootApplication
@MapperScan(basePackages = "com.hzy.gmall.publisher.mapper")
public class Gmall2022PublisherApplication {
public static void main(String[] args) {
SpringApplication.run(Gmall2022PublisherApplication.class, args);
}
}
c Service层:创建ProductStatsService接口
package com.hzy.gmall.publisher.service;
/**
* 商品统计service接口
*/
public interface ProductStatsService {
// 获取某天的总交易额
BigDecimal getGMV(Integer date);
}
d Service层:创建ProductStatsServiceImpl实现类
package com.hzy.gmall.publisher.service.impl;
/**
* 商品统计service接口实现类
*/
@Service
public class ProductStatsServiceImpl implements ProductStatsService{
@Autowired
private ProductStatsMapper productStatsMapper;
@Override
public BigDecimal getGMV(Integer date) {
return productStatsMapper.selectGMV(date);
}
}
e Controller层:创建SugarController类
该类主要接收用户请求,并做出响应。根据sugar不同的组件,返回不同的格式。
package com.hzy.gmall.publisher.controller;
/**
* 大屏展示控制层
*/
@RestController
@RequestMapping("/api/sugar")
public class SugarController {
@Autowired
private ProductStatsService productStatsService;
@RequestMapping("/gmv")
public String getGMV(@RequestParam(value = "date",defaultValue = "0") Integer date){
if (date == 0){
date = now();
}
// 调用service获取总交易额
BigDecimal gmv = productStatsService.getGMV(date);
String json = "{\"status\": 0,\"data\": "+gmv+"}";
return json;
}
// 获取当前日期
private Integer now() {
String yyyyMMdd = DateFormatUtils.format(new Date(), "yyyyMMdd");
return Integer.valueOf(yyyyMMdd);
}
}
(4)测试本地接口
a 启动SpringBoot应用程序
用浏览器访问测试接口
b 输出结果
输出结果一:
输出结果二: