Mongodb Aggregation Framework:最大日期的总和值

时间:2015-04-16 03:35:04

标签: mongodb aggregation-framework

我每周都会从服务中接收数据,并将其放入集合中。数据有一个amount,projectNo和dataDate时间戳。使用聚合框架,我按照projectNo和dataDate:

对数量和组进行求和
db.collection.aggregate([
    {$project: {projectNo: 1, bdgtAppd: 1, dataDate: 1}},
    {$group: {_id: {
                projectNo: "$projectNo", 
                dataDate: "$dataDate"
                }, 
            amount: {$sum: "$bdgtAppd"}}
    },
    {$project: {_id:0, 
                projectNo:"$_id.projectNo", 
                dataDate:"$_id.dataDate", 
                amount:"$amount"
                }
    },
    {$sort: {projectNo:1,dataDate:1}}
])

产生这个:

[{
    "amount" : 7887,
    "projectNo" : "5544A",
    "dataDate" : "2015-01-02T08:00:00.000Z"
}, {
    "amount" : 137947,
    "projectNo" : "5544A",
    "dataDate" : "2015-01-16T08:00:00.000Z"
}, {
    "amount" : 137947,
    "projectNo" : "5544A",
    "dataDate" : "2015-01-23T08:00:00.000Z"
}, {
    "amount" : 137947,
    "projectNo" : "5544A",
    "dataDate" : "2015-01-30T08:00:00.000Z"
}, {
    "amount" : 130060,
    "projectNo" : "5544A",
    "dataDate" : "2015-02-06T08:00:00.000Z"
}, {
    "amount" : 130060,
    "projectNo" : "5544A",
    "dataDate" : "2015-02-13T08:00:00.000Z"
}, {
    "amount" : 130060,
    "projectNo" : "5544A",
    "dataDate" : "2015-02-20T08:00:00.000Z"
}]

我现在需要做的是将返回的数据限制在该月的最后一个日期:

[{
    "amount" : 137947,
    "projectNo" : "5544A",
    "dataDate" : "2015-01-30T08:00:00.000Z"
}, {
    "amount" : 130060,
    "projectNo" : "5544A",
    "dataDate" : "2015-02-27T08:00:00.000Z"
}]

编辑:集合中的示例文档:

{
  "_id" : ObjectId("5527e724fc53ec16bc5fe57a"),
  "projectNo" : "5544G",
  "cpfoNo" : "1448R",
  "cpfoDate" : ISODate("2014-10-20T07:00:00Z"),
  "description" : "INC 6 CO 176 - Booster Pump",
  "pcoNo" : "1510",
  "approvedAmount" : null,
  "days" : null,
  "remarks" : null,
  "itemNo" : "0005",
  "costCode" : "5030.09900.0000.0000",
  "itemTitle" : "Painting - Hasson",
  "bdgtEst" : 0.0,
  "bdgtProp" : 745.0,
  "bdgtAprv" : 745.0,
  "bdgtAppd" : 745.0,
  "dataDate" : ISODate("2014-12-12T08:00:00Z")
}

2 个答案:

答案 0 :(得分:1)

不需要初始 $project 管道阶段,只需从 $group 步骤开始,以下管道阶段将产生期望的结果:

db.collection.aggregate([
    {
        "$group": {
            "_id": {
                "projectNo": "$projectNo", 
                "dataDate": "$dataDate"
            },
            "amount": {"$sum": "$bdgtAppd"}            
        }       
    },
    {
        "$project": {
            "_id": 0,            
            "projectNo": "$_id.projectNo",
            "dataDate": "$_id.dataDate",
            "amount": 1
        }
    },
    {
        "$group": {
            "_id": "$projectNo",                        
            "dataDate": {"$first" : "$dataDate"},  
            "amount": {"$first" : "$amount"}         
        }
    },
    {
        "$project": {
            "_id": 0,            
            "projectNo": "$_id",
            "dataDate": 1,
            "amount": 1
        }
    }
]);

使用以下示例文档(仅包括相关字段作为最小测试用例):

db.collection.insert([
    /* 0 */
    {
        "projectNo" : "5544A",
        "bdgtAppd" : 3,
        "dataDate" : ISODate("2015-01-02T08:00:00.000Z")
    },

    /* 1 */
    {
        "projectNo" : "5544A",
        "bdgtAppd" : 7,
        "dataDate" : ISODate("2015-01-28T08:00:00.000Z")
    },

    /* 2 */
    {
        "projectNo" : "5544A",
        "bdgtAppd" : 5,
        "dataDate" : ISODate("2015-01-28T08:00:00.000Z")
    },

    /* 3 */
    {
        "projectNo" : "5544B",
        "bdgtAppd" : 15,
        "dataDate" : ISODate("2015-02-13T08:00:00.000Z")
    },

    /* 4 */
    {
        "projectNo" : "5544G",
        "bdgtAppd" : 10,
        "dataDate" : ISODate("2015-02-27T08:00:00.000Z")
    },

    /* 5 */
    {
        "projectNo" : "5544G",
        "bdgtAppd" : 25,
        "dataDate" : ISODate("2015-02-27T08:00:00.000Z")
    },
]);

以上聚合产生:

/* 0 */
{
    "result" : [ 
        {
            "dataDate" : ISODate("2015-01-28T08:00:00.000Z"),
            "amount" : 12,
            "projectNo" : "5544A"
        }, 
        {
            "dataDate" : ISODate("2015-02-13T08:00:00.000Z"),
            "amount" : 15,
            "projectNo" : "5544B"
        }, 
        {
            "dataDate" : ISODate("2015-02-27T08:00:00.000Z"),
            "amount" : 35,
            "projectNo" : "5544G"
        }
    ],
    "ok" : 1
}

答案 1 :(得分:1)

感谢@chidrian让我开始。这是适合我的解决方案。可能是投射月份和年份键的额外步骤,但它可以工作。

{
    "$group": {
        "_id": {
            "projectNo": "$projectNo",
            "dataDate": "$dataDate"
        },
        "sum": "$bdgtAppd"
    }
}
}, {
    "$project": {
        "_id": 0,
        "projectNo": "$_id.projectNo",
        "dataDate": "$_id.dataDate",
        "amount": 1
    }
}, {
    "$project": {
        "_id": 0,
        "projectNo": "$projectNo",
        "amount": 1,
        "dataDate": 1,
        "month": {
            $month: "$dataDate"
        },
        "year": {
            "$year": "$dataDate"
        }
    }
}, {
    "$sort": {
        projectNo: 1,
        dataDate: 1
    }
}, {
    "$group": {
        "_id": {
            "projectNo": "$projectNo",
            "month": "$month",
            "year": "$year"
        },
        "dataDate": {
            "$last": "$dataDate"
        },
        "amount": {
            "$last": "$amount"
        }
    }
}, {
    "$sort": {
        projectNo: 1,
        dataDate: 1
    }
}, {
    "$project": {
        "_id": 0,
        "projectNo": "$_id.projectNo",
        "dataDate": 1,
        "amount": 1
    }
}