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

Field must be an accumulator object error when trying to group by object as key

我正在尝试通过集合中的多个属性对文档进行类型安全分组。我发现问题不在于多个属性本身的分组,而在于键是一个对象 (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: 'Command aggregate failed: The field 'Name' must be an accumulator object.'

当我将无效的查询转换为字符串时,我得到以下信息:

aggregate([{ "$group" : { "_id" : { "Name" : "$Name" }, "Name" : "$_id.Name", "Count" : { "$sum" : 1 } } }])

我猜这里的问题是这部分"Name" : "$_id.Name"。我该如何解决这个问题?

我目前使用的是 mongodb 驱动程序的 2.8.0 版。

实际上驱动程序在这里的行为是正确的,但您遇到的是聚合框架中 $group 管道阶段的限制。文档指出:

The output documents contain an _id field which contains the distinct group by key. The output documents can also contain computed fields that hold the values of some accumulator expression grouped by the $group’s _id field

因此,在您的情况下,您试图在没有任何累加器的情况下引用 _id 字段。

从逻辑角度看,您的查询似乎很相似。第一个被翻译成:

{
    "$group" : {
        "_id" : "$Name",
        "Count" : {
            "$sum" : 1
        }
    }
}

第二个 return 相同的数据,但您有一个对象作为分组键。要在 C# 中修复此问题,您需要引入 .First() 表达式,它将被翻译成 $first,因此 运行ning:

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
        }
    }
}

它有效,但逻辑上它return与第一个聚合

的数据相同