如何使用MongoDB C#驱动统计匹配文档Items子文档总数
需求
统计集合中所有Type字段值为"Test"的文档内,Items数组包含的子文档总数量。示例数据中2条匹配文档各包含2个Items子项,预期返回统计结果为4。
实现方式
根据数据规模可选择两种写法:
1. 客户端求和(小数据量场景)
写法最简单,查询匹配文档后直接在应用内存中累加数组长度,建议通过投影只返回数组长度,减少不必要的数据传输:
// 替换为实际业务实体类型 var coll = GetCollection<YourDocumentType>(); long total = coll.Find(p => p.Type == "Test") // 仅投影Items数组长度,不返回完整文档,加空值判断避免异常 .Project(p => p.Items != null ? p.Items.Length : 0) .ToEnumerable() .Sum();
注意:如果匹配的文档量级超过10万,不建议用这个方案,大量字段传输到应用侧会带来额外的网络和内存开销。
2. 服务端聚合(大数据量场景推荐)
通过MongoDB聚合管道直接在数据库侧完成过滤、求和计算,不需要传输原始文档到应用端,性能更高:
// 替换为实际业务实体类型 var coll = GetCollection<YourDocumentType>(); var aggResult = coll.Aggregate() // 第一步:过滤Type为Test的文档 .Match(p => p.Type == "Test") // 第二步:分组累加所有文档的Items数组长度 .Group( key => 1, g => new { Total = g.Sum(p => p.Items != null ? p.Items.Length : 0) } ) .FirstOrDefault(); long total = aggResult?.Total ?? 0;
如果使用的C# Mongo驱动版本较老,Lambda表达式无法正确映射数组长度计算,可以换成原生Bson写法,兼容性更好:
var coll = GetCollection<BsonDocument>(); var aggResult = coll.Aggregate() .Match(Builders<BsonDocument>.Filter.Eq("Type", "Test")) .Group(new BsonDocument { {"_id", 1}, {"Total", new BsonDocument("$sum", new BsonDocument("$size", new BsonDocument("$ifNull", new BsonArray{"$Items", new BsonArray()}) ))} }) .FirstOrDefault(); long total = aggResult?["Total"]?.AsInt64 ?? 0;
上述原生写法加了$ifNull逻辑,可自动处理文档中不存在Items字段、Items为null的异常场景。
内容的提问来源于stack exchange,提问作者mrcode
相关产品推荐
相关产品推荐

