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

时间:2019-05-02 10:59:20

标签: c# mongodb .net-core aggregation-framework mongodb-.net-driver

我正在尝试通过集合中的多个属性对组文档进行类型安全的处理。我发现问题不在于多个属性本身的分组,而是关键是对象(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驱动程序。

1 个答案:

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

它可以工作,但在逻辑上它返回的数据与第一次聚合相同