如何在不对聚合组的keyf函数进行任何更改的情况下指定原始参数

时间:2016-09-14 10:38:40

标签: mongodb mongodb-query aggregation-framework

这是我开始的简化收藏:

[{
  "_id" : ObjectId("577a598ecab5bb4a002c19da"),
  "user" : ObjectId("5775549f9fcaae26c9149026"),
  "expense" : 12.87,
  "created" : ISODate("2016-07-04T12:43:07.181Z")
},
{
  "_id" : ObjectId("577a598ecab5bb4a002c19db"),
  "user" : ObjectId("5775549f9fcaae26c9149026"),
  "expense" : 12.87,
  "created" : ISODate("2016-07-06T12:10:07.181Z")
},
{
  "_id" : ObjectId("977a598ecai6bb4a002c19du"),
  "user" : ObjectId("6775539f9fciae26c9149027"),
  "expense" : 12.87,
  "created" : ISODate("2016-07-07T10:43:07.181Z")
},
....
]

我希望在group参数的特定日期users并计算所有created

我正在尝试这个,但它不起作用:

db.getCollection('expenses').group({
            keyf: function(doc) {
               return { 
                   "day_created": doc.created.getDate(),
                   "user" : doc.user // or  "user" : 1
                }
            },
            cond: {},
            reduce: function (value, result) {
                result.total++;  
            },
            initial: {
                total: 0
            }
 });

相反,各个小组完美地工作(日期):

db.getCollection('expenses').group({
            keyf: function(doc) {
               return { 
                   "day_created": doc.created.getDate()
                }
            },
            cond: {},
            reduce: function (value, result) {
                result.total++;  
            },
            initial: {
                total: 0
            }
 });

响应

[
    {
        "day_created" : 17,
        "total" : 5385
    },
    {
        "day_created" : 18,
        "total" : 6338
    },
 ....
]

相反,各个小组完美地工作(对于用户而言):

db.getCollection('tickets').group({
            key : {user : 1},
            cond: {},
            reduce: function (value, result) {
                result.total++;  
            },
            initial: {
                total: 0
            }
 });

响应

[
    {
        "user" : ObjectId("5776f0143543e84a003d53bf"),
        "total" : 155
    },
    {
        "user" : ObjectId("577554a89fcaae26c914a8bd"),
        "total" : 494
    },
...
]

我正在使用MongoDB shell版本:3.2.1。如何使用计算字段进行组聚合而其他字段不进行?

1 个答案:

答案 0 :(得分:1)

您可以使用聚合框架来获取所需的聚合,而不是组功能。考虑运行以下管道:

db.getCollection('expenses').aggregate([
    {
        "$project": {
            "day_created": { 
                "$dateToString": { 
                    "format": "%Y-%m-%d", 
                    "date": "$created" 
                } 
            },
            "user": 1
        }
    },
    {
        "$group": {
            "_id": {
                "day_created": "$day_created",
                "user": "$user"
            },
            "total": { "$sum": 1 }
        }
    },
    {
        "$project": {
            "_id": 0
            "user": "$_id.user",
            "day_created": "$_id.day_created",
            "total": 1
        }
    }
])

在上面的管道中,第一个 $project 步骤将使用 $dateToString 运算符创建day_created字段。然后,下一个 $group 管道将按两个键user和新创建的day_created字段对文档进行分组,并使用 {{计算汇总数3}}

最后一个 $sum 管道步骤然后重新整形字段以输出所需的JSON结构。

要解决您的问题,您需要将created日期转换为唯一代表该日期的日期格式。

尝试运行以下内容:

db.getCollection('expenses').group({
    keyf: function(doc) {
        var month = '' + (doc.created.getMonth() + 1),
        day = '' + doc.created.getDate(),
        year = doc.created.getFullYear();

        if (month.length < 2) month = '0' + month;
        if (day.length < 2) day = '0' + day;

        var day_created = [year, month, day].join('-');
        return { 
            "day_created": day_created,
            "user" : doc.user 
        }
    },
    cond: {},
    reduce: function (value, result) {
        result.total++;  
    },
    initial: {
        total: 0
    }
})