MongoDB如何按月份和年份进行聚合

9

我是mongodb的新手,正在努力学习Mongodb查询。

    {
    "_id" : ObjectId("59815d4704ca1760a45957ca"),
    "userEmail" : "lk@gmail.com",
    "expenseAmount" : 200,
    "expenseRemark" : "aa",
    "expenseCategory" : "billing",
    "entryTime" : ISODate("2017-08-02T05:03:57Z"),
    "__v" : 0
}
{
    "_id" : ObjectId("59815d5404ca1760a45957cb"),
    "userEmail" : "lk@gmail.com",
    "expenseAmount" : 300,
    "expenseRemark" : "ff",
    "expenseCategory" : "transport",
    "entryTime" : ISODate("2017-08-02T05:04:11Z"),
    "__v" : 0
}
{
    "_id" : ObjectId("5980191d04ca1760a45957cd"),
    "userEmail" : "lk@gmail.com",
    "expenseAmount" : 100,
    "expenseRemark" : "rr",
    "expenseCategory" : "billing",
    "entryTime" : ISODate("2017-08-01T06:00:46Z"),
    "__v" : 0
}
{
    "_id" : ObjectId("5980192604ca1760a45957ce"),
    "userEmail" : "lk@gmail.com",
    "expenseAmount" : 200,
    "expenseRemark" : "qq",
    "expenseCategory" : "transport",
    "entryTime" : ISODate("2017-08-01T06:01:03Z"),
    "__v" : 0
}
{
    "_id" : ObjectId("5980192e04ca1760a45957cf"),
    "userEmail" : "lk@gmail.com",
    "expenseAmount" : 470,
    "expenseRemark" : "ff",
    "expenseCategory" : "transport",
    "entryTime" : ISODate("2017-08-01T06:01:11Z"),
    "__v" : 0
}
{
    "_id" : ObjectId("59816ac004ca1760a45957d0"),
    "userEmail" : "lk@gmail.com",
    "expenseAmount" : 500,
    "expenseRemark" : "raj",
    "expenseCategory" : "transport",
    "entryTime" : ISODate("2017-08-02T06:01:26Z"),
    "__v" : 0
}
{
    "_id" : ObjectId("59816acb04ca1760a45957d1"),
    "userEmail" : "lk@gmail.com",
    "expenseAmount" : 100,
    "expenseRemark" : "pet",
    "expenseCategory" : "pets",
    "entryTime" : ISODate("2017-08-02T06:01:37Z"),
    "__v" : 0
}
{
    "_id" : ObjectId("597d7a9c04ca1760a45957d2"),
    "userEmail" : "lk@gmail.com",
    "expenseAmount" : 500,
    "expenseRemark" : "gt",
    "expenseCategory" : "sports",
    "entryTime" : ISODate("2017-07-30T06:20:04Z"),
    "__v" : 0
}
{
    "_id" : ObjectId("597d7aaa04ca1760a45957d3"),
    "userEmail" : "lk@gmail.com",
    "expenseAmount" : 560,
    "expenseRemark" : "mov",
    "expenseCategory" : "entertainment",
    "entryTime" : ISODate("2017-07-30T06:20:14Z"),
    "__v" : 0
}

我希望能按照年份+月份的方式来对expenseAmount进行分组。 我尝试过:

`db.expenses.aggregate( 
       {$project : { 
              month : {$month : "$entryTime"}, 
              year : {$year :  "$entryTime"}
          }}, 
        {$group : { 
                _id : {month : "$month" ,year : "$year" },  
              total : {$sum : "$expenseAmount"} 
        }})`

这提供了

{ "_id" : { "month" : 7, "year" : 2017 }, "total" : 0 }

{ "_id" : { "month" : 8, "year" : 2017 }, "total" : 0 }

请指导我如何获取汇总结果。 我无法弄清楚如何做到这一点。
谢谢。

因为$project只返回您告诉它的字段。相反,您应该在$group中编写整个内容。这样更有效率。 - Neil Lunn
3个回答

14
在投影阶段,您丢失了expenseAmount字段。只需简单地添加它:
{$project: { 
    month: { $month: "$entryTime" }, 
    year: { $year: "$entryTime" },
    expenseAmount: 1
}},

请注意,如果字段在文档中不存在,则$sum返回0。
另外,请注意还有另一个聚合操作符$addFields,它按照您的预期进行操作。它会向文档添加新字段,并保留输入文档中的所有现有字段。但在这种情况下,您只需要expenseAmount字段。

我该如何使用$addFields,请指导。 - raju
在这种情况下,@raju不需要它,因为您只需要从输入文档中使用expenseAmount字段。但是,如果您还需要输入文档中的其他字段,则可以使用$addFields(答案中的链接可点击)指定要添加到文档现有字段中的字段,而不是手动通过$project运算符全部包含它们。 - Sergey Berezovskiy

2
  db.expenses.aggregate( 
    {$group : { 
            _id : { 
          month : {$month : "$entryTime"}, 
          year : {$year :  "$entryTime"}
      }},  
          total : {$sum : "$expenseAmount"} 
    }})

无需添加“项目”,只需使用“组”即可完成所有操作。

-1
在这种情况下,不需要使用$project。只需使用以下内容即可获得预期结果。
 db.expenses.aggregate( 
   {$group : { 
           _id : { 
         month : {$month : "$entryTime"}, 
         year : {$year :  "$entryTime"}
     }},  
         total : {$sum : "$expenseAmount"} 
   }})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接