我正在尝试通过集合中的多个属性对组文档进行类型安全的处理。我发现问题不在于多个属性本身的分组,而是关键是对象(new { }
)而不是字符串。
这有效:
collection.Aggregate().Group(x => x.Name, x => new { Name = x.Key, Count = x.Sum(s => 1) }).ToList();
这不起作用:
collection.Aggregate().Group(x => new { Name = x.Name }, x => new { Name = x.Key.Name, Count = x.Sum(s => 1) }).ToList();
错误是:
MongoDB.Driver.MongoCommandException:'命令聚合失败:'Name'字段必须是累加器对象。'
当我将无法使用的查询转换为字符串时,得到以下信息:
aggregate([{ "$group" : { "_id" : { "Name" : "$Name" }, "Name" : "$_id.Name", "Count" : { "$sum" : 1 } } }])
我想这里的问题是这部分"Name" : "$_id.Name"
。我该如何解决这个问题?
我当前正在使用2.8.0版的mongodb驱动程序。
答案 0 :(得分:2)
实际上,驱动程序在此处的行为正确,但是您遇到的是Aggregation Framework中$group流水线阶段的局限性。该文档指出:
输出文档包含_id字段,该字段包含按键区分的组。输出文档还可以包含计算字段,其中包含某些累加器表达式的值,这些表达式按$ group的_id字段
分组
因此,在您的情况下,您尝试不带任何累加器地引用_id
字段。
从逻辑角度看,您的查询似乎是相似的。第一个被翻译成:
{
"$group" : {
"_id" : "$Name",
"Count" : {
"$sum" : 1
}
}
}
第二个将返回相同的数据,但是您有一个对象作为分组键。要在C#中解决此问题,您需要引入.First()
表达式,该表达式将转换为$first,因此运行:
Col.Aggregate()
.Group(
x => new { Name = x.Name },
x => new { Name = x.First().Name, Count = x.Sum(s => 1) })
.ToList();
将在数据库查询下面运行:
{
"$group" : {
"_id" : {
"Name" : "$Name"
},
"Name" : {
"$first" : "$Name"
},
"Count" : {
"$sum" : 1
}
}
}
它可以工作,但在逻辑上它返回的数据与第一次聚合相同