MongoDB C# Driver v2.21:将时间桶转换为日期键字典结构
问题描述
我们有一个存储每日交易汇总的MongoDB文档集合,原始Schema如下:
{ "licenseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "transactionDay":"2023-08-23", "startTime": "2023-08-23T13:00:00Z", "endTime": "2023-08-23T13:01:00Z", "count": 1, "size": 12345 }
需要生成如下格式的报表,将每日的count和size总计以transactionDay为键存入字典结构:
{ "licenseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "usage": { "2023-08-23": { "countTotal": 1, "sizeTotal": 12345 } } }
目前使用MongoDB C# Driver v2.21的聚合Fluent语法,只能生成每日汇总但无法得到目标格式,现有代码如下:
var usageReport = transactionCollection.Aggregate() .Match(licenseFilter) .Group( e => e.transactionDay, g => new { transactionDay= g.Key, licenseId= g.First().licenseId, sizeTotal= g.Sum(x=>x.size), countTotal= g.Sum(x=>x.count) }) .ToList();
不清楚是缺少Projection阶段还是Group方式有误,需要实现该需求的指引。
解决方案
要得到目标格式,核心是调整聚合逻辑的分组层级:先按licenseId分组,在组内整理每日汇总数据并转换为字典结构,具体实现如下:
Fluent语法实现
var usageReport = transactionCollection.Aggregate() .Match(licenseFilter) // 第一步:按licenseId分组,组内按transactionDay计算每日汇总 .Group( e => e.licenseId, g => new { LicenseId = g.Key, DailyUsage = g.Group(x => x.transactionDay, dayGroup => new { Key = dayGroup.Key, Value = new { countTotal = dayGroup.Sum(x => x.count), sizeTotal = dayGroup.Sum(x => x.size) } }) }) // 第二步:将每日汇总数组转为字典结构,生成最终格式 .Project(result => new { result.LicenseId, Usage = result.DailyUsage.ToDictionary(kv => kv.Key, kv => kv.Value) }) .ToList();
原生聚合语法实现(贴近MongoDB原生操作)
var usageReport = transactionCollection.Aggregate() .Match(licenseFilter) .Group( new BsonDocument("_id", "$licenseId"), new BsonDocument { { "dailyUsage", new BsonDocument("$push", new BsonDocument { { "k", "$transactionDay" }, { "v", new BsonDocument { { "countTotal", "$count" }, { "sizeTotal", "$size" } } } }) } }) .Project(new BsonDocument { { "licenseId", "$_id" }, { "usage", new BsonDocument("$arrayToObject", "$dailyUsage") }, { "_id", 0 } }) .ToList();
关键说明
- 原代码的问题在于按transactionDay分组,导致结果是多个按日期拆分的文档,而目标是每个
licenseId对应一个整合所有日期汇总的文档。 - 必须先按
licenseId分组,在组内完成每日数据的汇总和结构转换,才能将所有日期的统计结果整合到一个usage字典中。 - 使用
ToDictionary(Fluent语法)或$arrayToObject(原生聚合)是实现字典结构的核心操作。
内容的提问来源于stack exchange,提问作者PeeGee
相关产品推荐
相关产品推荐

