MongoDB聚合分组后如何将Casts数组上提一级?
解决MongoDB聚合中Casts二维数组转一维数组的问题
嗨,刚接触MongoDB遇到这种小问题很正常~你当前的聚合结果里Casts变成二维数组,是因为直接用$push:"$Casts"时,把每个文档里的整个Casts数组当作单个元素推入了结果数组,自然就嵌套成二维的了。咱们调整下聚合逻辑就能搞定:
核心解决方案:用$push配合$each展开数组
在$group阶段的Casts字段中,通过$each操作符把每个文档的Casts数组拆分成单个元素再推入,这样最终得到的就是一维数组。完整的MongoDB Shell查询如下:
db.getCollection('myCollection').aggregate([ { $group: { "_id": "$Category", "count": { $sum: 1 }, "Casts": { $push: { $each: "$Casts" } } } } ])
如果你的业务需要对演员信息去重(比如同一个演员出现在多部影片里,只想保留一条记录),可以把$push换成$addToSet,同样搭配$each使用:
db.getCollection('myCollection').aggregate([ { $group: { "_id": "$Category", "count": { $sum: 1 }, "Casts": { $addToSet: { $each: "$Casts" } } } } ])
C#代码实现(基于MongoDB.Driver)
既然你用C#开发,这里给你对应官方驱动的代码示例:
用BsonDocument的通用写法
var collection = mongoDatabase.GetCollection<BsonDocument>("myCollection"); var aggregate = collection.Aggregate() .Group( x => x["Category"], g => new { Category = g.Key, Count = g.Sum(x => 1), Casts = g.PushEach(x => x["Casts"].AsBsonArray) } ); var result = await aggregate.ToListAsync();
用实体类的强类型写法
如果你已经定义了对应的实体类,代码会更简洁:
// 先定义实体类 public class Movie { public int Id { get; set; } public string Title { get; set; } public List<string> Genres { get; set; } public int Category { get; set; } public List<Cast> Casts { get; set; } } public class Cast { public int Id { get; set; } public string Name { get; set; } public string Gender { get; set; } public int Age { get; set; } } // 聚合查询逻辑 var collection = mongoDatabase.GetCollection<Movie>("myCollection"); var aggregate = collection.Aggregate<Movie>() .Group( movie => movie.Category, group => new { Category = group.Key, Count = group.Count(), Casts = group.SelectMany(movie => movie.Casts).ToList() } ); var result = await aggregate.ToListAsync();
性能提示
你的数据集有500万条,建议给Category字段创建索引,能大幅提升聚合效率:
db.myCollection.createIndex({ Category: 1 })
另外如果聚合后的Casts数组过大,可能会触及MongoDB的文档大小限制(16MB),这种情况下可以考虑只保留需要的演员字段,或者分批次处理结果。
内容的提问来源于stack exchange,提问作者Mhmd
相关产品推荐
相关产品推荐

