指标数据查看的细节分析(下)
在上一篇章节中,讲到了再查询数据时,需要有 数据获取执行器,这里使用到了策略模式,对于数据获取执行器有三种策略:
- VideoReportDataFetchExecutor: 视频报表数据获取执行器
- VideoTypeReportDataFetchExecutor: 视频类型报表数据获取执行器
- ParentVideoTypeReportDataFetchExecutor: 父视频类型报表数据获取执行器
详细详解了 视频报表数据获取执行器 的执行流程,而在核心的流程中用到了模板模式,所以核心其实是在父类AbstractReportDataFetchExecutor中了。
执行总览(从 execute 开始)
org.javaup.handler.core.queryfetch.AbstractReportDataFetchExecutor
入口方法:execute(totalParamTransfers)
- 获取查询入参
QueryDataTransfers - 通过实现类先查“维度数据”(视频列表)
- 基于维度数据查询指标数据
- 过滤掉配置为“不显示”的指标
- 按维度进行分组汇总,构建“维度值 → 指标值映射”
- 组装行数据(含第一行“累记”)
- 组装
ReportVo并封装进RuleHandleOutput返回
public RuleHandleOutput execute(TotalParamTransfers totalParamTransfers) {
RuleHandleOutput ruleHandleOutput = new RuleHandleOutput();
QueryDataTransfers queryDataTransfers = totalParamTransfers.getParamTransfers().getQueryDataTransfers();
//查询视频维度
List<T> dimensionDataList = fetchDimensionData(queryDataTransfers);
if (CollectionUtils.isEmpty(dimensionDataList)) {
return ruleHandleOutput;
}
//获取到维度数据
List<Map<String, Object>> metricDataList = getMetricDataList(queryDataTransfers, dimensionDataList);
if (CollectionUtils.isEmpty(metricDataList)) {
return ruleHandleOutput;
}
List<Metric> metricList = metricService.selectByRuleId(totalParamTransfers.getParamTransfers().getRuleId());
//metricShowStatusMap:指标名称与显示状态的映射
Map<String, Integer> metricShowStatusMap = metricList.stream().collect(Collectors.toMap(Metric::getMetricName,
Metric::getShowStatus));
//这里是过滤掉不显示的指标
List<Map<String, Object>> filterMetricDataList = new ArrayList<>(metricDataList.size());
for (Map<String, Object> metricDataMap : metricDataList) {
Map<String, Object> filterMetricDataMap = MapUtil.newHashMap();
for (Entry<String, Object> entry : metricDataMap.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
Integer showStatus = metricShowStatusMap.get(key);
//showStatus为空,或者显示状态为显示,那么就放入新的指标数据中
//如果showStatus为空,说明是分组字段,比如video_id、video_type_id等,这些字段都是要显示的
if (Objects.isNull(showStatus) || showStatus.equals(ShowStatus.YES.getCode())) {
filterMetricDataMap.put(key, value);
}
}
filterMetricDataList.add(filterMetricDataMap);
}
List<String> filterMetricNameList = queryDataTransfers.getQueryDataExecuteTransfers().getMetricList().stream()
.map(Metric::getMetricName)
.filter(metricName -> ShowStatus.YES.getCode().equals(metricShowStatusMap.get(metricName))).toList();
List<String> filterMetricDescribeList = queryDataTransfers.getQueryDataExecuteTransfers().getMetricList()
.stream()
.filter(metric -> ShowStatus.YES.getCode().equals(metricShowStatusMap.get(metric.getMetricName())))
.map(Metric::getMetricDescribe)
.toList();
//将指标数据进行分组
//如果是视频维度,那么按照视频id进行分组 key:视频id value:指标数据
//如果是视频维度,那么按照视频分类id进行分组 key:视频分类id value:指标数据
Map<Object, Map<String, Object>> metricMap = groupByMetricDataList(queryDataTransfers,filterMetricDataList);
//组装行的指标数据集合
List<RowDataVo> rowDataVoList = assembleRowDataList(dimensionDataList, metricMap, filterMetricNameList);
//设置报表数据
ReportVo reportVo = new ReportVo();
//规则信息
reportVo.setRuleDescribe(queryDataTransfers.getQueryDataExecuteTransfers().getRuleDescribe());
//报表的统计时间
reportVo.setDateTime(DateTimeFunc.getEntryName(queryDataTransfers.getDateType(), queryDataTransfers.getStartTime(),
queryDataTransfers.getEndTime()));
//报表的列名
List<String> columnNameList = new ArrayList<>();
//第一个列名是维度名称
columnNameList.add(queryDataTransfers.getQueryDataExecuteTransfers().getAccumulateColumnName());
//后面是指标列名
columnNameList.addAll(filterMetricDescribeList);
reportVo.setColumnNameList(columnNameList);
//行数据
reportVo.setRowDataVoList(rowDataVoList);
ruleHandleOutput.setReportVo(reportVo);
return ruleHandleOutput;
}
在上一章节中,讲到了获取到维度数据(getMetricDataList)方法执行的流程,得到了metricDataList实际的指标数据
metricDataList真实数据结构
[
{
"video_id": 7762202481762402600,
"watch_count": 123,
"watch_like_count": 3,
"watch_dislike_count": 0,
"watch_complete_count": 34,
"watch_like_rate": 0.02,
"watch_dislike_rate": 0,
"watch_complete_rate": 0.28
},
{
"video_id": 7762202481762402601,
"watch_count": 129,
"watch_like_count": 17,
"watch_dislike_count": 0,
"watch_complete_count": 23,
"watch_like_rate": 0.13,
"watch_dislike_rate": 0,
"watch_complete_rate": 0.18
}
]
指标过滤的双重处理机制
在获取到原始指标数据后、进行分组之前,有一个双重过滤机制来处理"哪些指标需要显示":
第一重过滤:过滤指标数据行中的列
这一步是对数据行进行过滤,即从数据库查询返回的 metricDataList 中,把每一行里"不需要显示的指标列"剔除掉。
List<Metric> metricList = metricService.selectByRuleId(totalParamTransfers.getParamTransfers().getRuleId());
//metricShowStatusMap:指标名称与显示状态的映射
Map<String, Integer> metricShowStatusMap = metricList.stream().collect(Collectors.toMap(Metric::getMetricName,
Metric::getShowStatus));
//这里是过滤掉不显示的指标
List<Map<String, Object>> filterMetricDataList = new ArrayList<>(metricDataList.size());
for (Map<String, Object> metricDataMap : metricDataList) {
Map<String, Object> filterMetricDataMap = MapUtil.newHashMap();
for (Entry<String, Object> entry : metricDataMap.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
Integer showStatus = metricShowStatusMap.get(key);
//showStatus为空,或者显示状态为显示,那么就放入新的指标数据中
//如果showStatus为空,说明是分组字段,比如video_id、video_type_id等,这些字段都是要显示的
if (Objects.isNull(showStatus) || showStatus.equals(ShowStatus.YES.getCode())) {
filterMetricDataMap.put(key, value);
}
}
filterMetricDataList.add(filterMetricDataMap);
}
1. 构建映射表 metricShowStatusMap:
- 从数据库查询该规则下的所有指标配置
- 建立"指标名称 → 显示状态"的映射关系
- 例如:
{"watch_count": 123, "watch_like_count": 1,}
2. 遍历每行数据的每个键值对:
- 对于每个字段(key),去
metricShowStatusMap中查找它的显示状态 - 如果
showStatus == null:说明这个字段不是指标字段,而是分组维度字段(如video_id、video_type_id),必须保留 - 如果
showStatus == ShowStatus.YES:说明这是需要显示的指标,保留 - 其他情况(showStatus 为 NO):不保留,过滤掉
3. 结果:
- 原始数据行可能包含 10 个字段,过滤后可能只剩 7 个(1 个维度字段 + 6 个需要显示的指标)
- 得到
filterMetricDataList,每行只保留需要的字段
举例说明:
假设从数据库查到一行数据:
{
"video_id": 101, // 分组字段
"watch_count": 1000, // 指标,showStatus=YES
"watch_like_count": 50, // 指标,showStatus=YES
"internal_metric": 123, // 指标,showStatus=NO(不显示)
"watch_complete_count": 800 // 指标,showStatus=YES
}
过滤后:
付费内容提示
该文档的全部内容仅对「码力全开」项目实战&技术讲解 知识星球用户开放
加入星球,一次获得完整项目资料、全栈技术知识库和长期答疑服务。
100万+字全栈技术知识库深入讲解技术核心、数据库、中间件和分布式等内容
8套热门的实战项目持续更新的企业级项目覆盖高并发、微服务、数据中台 和 AI Agent 等方向
AI 技术知识大模型面试详解覆盖 AI 模型原理、Agent、RAG、MCP、Skills、Harness 等核心知识点
文档 + 视频两种讲解形式既能系统阅读,也能跟随视频理解核心业务
完整项目实战资料
每套项目均包含从 0 到 1 讲解文档核心业务讲解视频从基础项目到复杂业务场景,项目资料会持续更新。
- 01Nexus Agent AI 智能体
- 02Nexus Agent Pro 完全版
- 03黑马点评Plus
- 04大麦
- 05大麦Pro
- 06大麦AI
- 07流量切换
- 08数据中台
加入后还能获得
进入星球后,即可享受上述所有服务,保证不会再有其他隐藏费用。从学习、面试到项目启动,都可以继续获得支持。
- 1 对 1 解答项目和技术问题都可以提问
- 针对性补充没有讲清楚的内容会继续补充
- 面试与简历指导梳理回答技巧和项目亮点
- 中间件云环境项目依赖可以直接接入使用
- 面试后复盘被问住的问题可以继续交流
- 远程问题解决项目启动问题可协助排查
