尝试按对象分组作为键时,字段必须是累加器对象错误
Posted
技术标签:
【中文标题】尝试按对象分组作为键时,字段必须是累加器对象错误【英文标题】:Field must be an accumulator object error when trying to group by object as key 【发布时间】:2019-09-20 21:17:43 【问题描述】:我正在尝试按集合中的多个属性对文档进行类型安全分组。我发现问题不在于多个属性本身的分组,而是关键是一个对象(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:'命令聚合失败:字段'名称'必须是累加器对象。'
当我将不起作用的查询转换为字符串时,我得到以下信息:
aggregate([ "$group" : "_id" : "Name" : "$Name" , "Name" : "$_id.Name", "Count" : "$sum" : 1 ])
我想这里的问题是这部分"Name" : "$_id.Name"
。我该如何解决这个问题?
我目前正在使用 2.8.0 版本的 mongodb 驱动程序。
【问题讨论】:
【参考方案1】:实际上,驱动程序在这里运行正常,但您遇到的是聚合框架中$group 管道阶段的限制。该文档指出:
输出文档包含一个 _id 字段,其中包含按键的不同组。输出文档还可以包含计算字段,这些字段包含由 $group 的 _id 字段分组的某些 accumulator 表达式的值
因此,在您的情况下,您尝试在没有任何累加器的情况下引用 _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
它可以工作,但逻辑上它返回与第一次聚合相同的数据
【讨论】:
以上是关于尝试按对象分组作为键时,字段必须是累加器对象错误的主要内容,如果未能解决你的问题,请参考以下文章
MongoDB 聚合错误:管道阶段规范对象必须只包含一个字段