/v2/summary 接口逻辑梳理
本文档旨在清晰地解释 /v2/summary 接口的完整工作流程,包括从前端请求到返回结果的整个过程。
1. 接口概览
/v2/summary 是一个用于获取用户活动汇总统计信息的 RESTful API 接口。该接口允许客户端根据时间范围、时区、文章 ID 和广告来源等条件查询用户行为的汇总数据。
1.1 接口签名
GET /v2/summary?startDate={startDate}&endDate={endDate}&zoneId={zoneId}&postId={postId}&fromAd={fromAd}
1.2 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| startDate | String | 是 | 查询开始日期,格式为 "YYYY-MM-DD" |
| endDate | String | 是 | 查询结束日期,格式为 "YYYY-MM-DD" |
| zoneId | String | 是 | 时区标识符 |
| postId | String | 是 | 文章 ID |
| fromAd | Boolean | 否 | 是否来源于广告 |
1.3 返回值
返回一个包含用户活动汇总信息的对象,具体字段如下:
- uniqueVisitors: 唯一访客数
- engaged: 互动用户数
- viewedProduct: 查看商品用户数
- clickedAddToCart: 点击加购按钮用户数
- clickedBuyNow: 点击立即购买按钮用户数
- initiatedCheckout: 发起结账流程用户数
- addedToCart: 添加到购物车用户数
- placedOrder: 下单用户数
- orderQuantity: 订单数量
- device: 设备类型分布
- platform: 平台分布
- ui: UI 版本分布
2. 调用链路详解
2.1 Controller 层处理
@GetMapping("/v2/summary")
public R<?> getSummaryV2(String startDate, String endDate, String zoneId, String postId, Boolean fromAd) {
R<String> checked = checkParamsForSummaryAndStatistic(startDate, endDate, zoneId, postId);
if (null != checked) return checked;
return R.result(Success, userActivityService.uniqueVisitorActionSummaryByPostV2(pearEnv, startDate, endDate, zoneId, postId, fromAd));
}
此方法执行以下操作:
- 使用 checkParamsForSummaryAndStatistic 方法验证输入参数的有效性
- 如果参数验证失败,直接返回错误信息
- 如果参数验证成功,调用 Service 层的 uniqueVisitorActionSummaryByPostV2 方法获取汇总数据
2.2 Service 层处理
@Override
public UserActivitySummary uniqueVisitorActionSummaryByPostV2(String environment, String startDate, String endDate,
String zoneId, String postId, Boolean fromAd) {
return userActivitySummaryRepositoryV2.summaryUserActivity(environment, startDate, endDate, zoneId, postId, fromAd);
}
Service 层主要起到桥梁作用,将请求转发给 Repository 层处理。
2.3 Repository 层处理
@Override
public UserActivitySummary summaryUserActivity(String environment, String startDate, String endDate, String zoneId, String postId, Boolean fromAd) {
MongoCollection<Document> summaryCollection = mongoTemplate.getCollection("%sUserActivitySummary_%s_v2".formatted(environment, zoneId));
List<BsonDocument> summaryPipe = new ArrayList<>() {{
add(uaa.matchSummaryRange(postId, startDate, endDate, fromAd));
add(uaa.summaryUserActivity());
add(uaa.expandSummary());
}};
AggregateIterable<Document> summary = summaryCollection.aggregate(summaryPipe);
return UserActivitySummary.convertDocument(summary.first());
}
Repository 层执行以下关键步骤:
获取对应环境和时区的 MongoDB 集合:
MongoCollection<Document> summaryCollection = mongoTemplate.getCollection("%sUserActivitySummary_%s_v2".formatted(environment, zoneId));构建聚合管道(Aggregation Pipeline):
- matchSummaryRange:匹配指定的文章ID、日期范围和广告来源
- summaryUserActivity:对匹配的数据进行汇总计算
- expandSummary:展开聚合结果
执行聚合查询并获取第一条结果
使用 UserActivitySummary.convertDocument 方法将 MongoDB 的 Document 转换为 Java 对象
2.4 聚合管道详解
2.4.1 匹配阶段 (matchSummaryRange)
构建查询条件,筛选符合以下条件的记录:
2.4.2 汇总阶段 (summaryUserActivity)
使用 MongoDB 的 $group 和 $accumulator 操作符对匹配的数据进行汇总计算:
初始化累加器状态:
function() { return { uniqueVisitors: 0, engaged: 0, viewedProduct: 0, clickedAddToCart: 0, clickedBuyNow: 0, initiatedCheckout: 0, placedOrder: 0, addedToCart: 0, orderQuantity: 0, device: {}, platform: {}, ui: {} }; }累加处理每条记录:
function(summary, record) { if (record["uniqueVisitors"] > 0) summary["uniqueVisitors"] += record["uniqueVisitors"]; if (record["engaged"] > 0) summary["engaged"] += record["engaged"]; // ... 其他字段类似处理 // 合并设备、平台和UI版本的分布统计 return summary; }
2.4.3 结果展开阶段 (expandSummary)
使用 $project 操作符将聚合结果展开,去除 _id 字段,保留所需的统计字段。
2.5 数据转换 (convertDocument)
将 MongoDB 返回的 Document 对象转换为 UserActivitySummary Java 对象:
public static UserActivitySummary convertDocument(Document document) {
if (null == document) return null;
UserActivitySummary summary = new UserActivitySummary();
summary.uniqueVisitors = document.getDouble("uniqueVisitors").intValue();
summary.engaged = document.getDouble("engaged").intValue();
summary.viewedProduct = document.getDouble("viewedProduct").intValue();
summary.clickedAddToCart = document.getDouble("clickedAddToCart").intValue();
summary.clickedBuyNow = document.getDouble("clickedBuyNow").intValue();
summary.initiatedCheckout = document.getDouble("initiatedCheckout").intValue();
summary.addedToCart = document.getDouble("addedToCart").intValue();
summary.placedOrder = document.getDouble("placedOrder").intValue();
summary.orderQuantity = document.getDouble("orderQuantity").intValue();
summary.device = document.get("device");
summary.platform = document.get("platform");
summary.ui = document.get("ui");
return summary;
}
3. 总结
/v2/summary 接口通过 MongoDB 聚合管道实现了高效的数据汇总功能。其核心逻辑包括:
- 参数校验与传递
- 构造 MongoDB 查询条件
- 使用聚合管道进行数据筛选、汇总和格式化
- 将结果转换为 Java 对象并返回给客户端
整个流程充分利用了 MongoDB 的聚合框架能力,在数据库层面完成了复杂的统计计算,避免了在应用层处理大量数据,提高了系统性能。