尝试按对象分组作为键时,字段必须是累加器对象错误

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 聚合错误:管道阶段规范对象必须只包含一个字段

尝试将行附加到按对象分组中的每个组时的奇怪行为

Jquery 或 PHP 按日期字段分组对象数组

GraphQL 错误“字段必须是以字段名称作为键的对象或返回此类对象的函数。”

一句话实现MySQL库中的按条件变化分组