You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MongoDB .NET Driver实现数据分组并返回关联文档数据的技术问题

解决MongoDB .NET Driver v2.13中$addToSet聚合操作的错误

嘿,我一眼就看出你代码里的问题了——你把$addToSet的结构搞反了!在MongoDB的聚合$group阶段,字段名应该是你要输出的键(比如names),而$addToSet是这个字段对应的操作符,你之前把$addToSet当成了键,这就导致驱动识别不了这个合法的聚合操作,所以才会报错。

错误原因拆解

你原来的代码里,$addToSet被写成了$group对象的键:

{ "$addToSet", new BsonDocument { {"names", "$name"}, } }

这完全不符合MongoDB聚合的语法规范,正确的结构应该是输出字段名作为键,值是包含$addToSet操作的文档。

修正后的BsonDocument写法

直接调整$group内的结构,把names作为字段键,$addToSet作为操作符放在值里:

var group = new BsonDocument
{
    { "$group", new BsonDocument
        {
            { "_id", new BsonDocument { { "grade", "$grade" } } },
            { "count", new BsonDocument { { "$sum", 1 } } },
            // 正确结构:字段名是names,值是$addToSet操作
            { "names", new BsonDocument { { "$addToSet", "$name" } } }
        }
    }
};

var pipeline = new[] { group };
await col.Aggregate<BsonDocument>(pipeline)
         .ForEachAsync(doc => 
         {
             // 处理结果,比如打印输出
             Console.WriteLine(doc.ToJson());
         });

更简洁的AggregateBuilder写法

如果你觉得BsonDocument写起来容易出错,推荐使用MongoDB .NET Driver的AggregateBuilder,它的强类型写法更直观:

// 假设你的集合实体类名为Student(如果没有实体类,也可以用BsonDocument)
var pipeline = col.Aggregate()
    .Group(
        // 按grade字段分组
        key => key["grade"].AsString,
        // 定义分组后的输出结构
        group => new 
        {
            grade = group.Key,
            // ToHashSet()对应MongoDB的$addToSet操作
            names = group.Select(s => s["name"].AsString).ToHashSet(),
            // Count()对应$sum:1
            count = group.Count()
        }
    );

await pipeline.ForEachAsync(result =>
{
    Console.WriteLine($"Grade: {result.grade}, Names: {string.Join(", ", result.names)}, Count: {result.count}");
});

优化输出结构(可选)

如果想把_id.grade直接改成顶级的grade字段,去掉默认的_id,可以在聚合pipeline里再加一个$project阶段:

var project = new BsonDocument
{
    { "$project", new BsonDocument
        {
            { "grade", "$_id.grade" },
            { "names", 1 },
            { "count", 1 },
            { "_id", 0 } // 隐藏_id字段
        }
    }
};

var pipeline = new[] { group, project };

这样就能得到完全和你期望一致的输出格式:

{ "grade": "A", "names": ["amy", "doug"], "count": 2 }
{ "grade": "B", "names": ["cathy"], "count": 1 }
{ "grade": "C", "names": ["edith", "frank"], "count": 2 }
{ "grade": "D", "names": ["bob"], "count": 1 }

内容的提问来源于stack exchange,提问作者InfiniteLoop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 13:38:15