【问题标题】:Mongodb Aggregation Framework: Sum values for max date in monthMongodb聚合框架:每月最大日期的总和值
【发布时间】:2015-04-16 03:35:04
【问题描述】:

我每周都会收到来自服务的数据,并将这些数据放入一个集合中。数据有数量、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")
}

【问题讨论】:

  • 你能把你的文件给我们看看吗?
  • @Michael 你有机会看看这个吗?

标签: mongodb aggregation-framework


【解决方案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
}

【讨论】:

  • 感谢您的提示,我认为将密钥限制为仅我关心的密钥会加快速度,但我忘记了 $group 做同样的事情。这种聚合让我非常接近,在某些情况下它是正确的,而在其他情况下它选择了当月的第一个 dataDate。我觉得有一种方法可以一次性完成,但我担心我必须先获取日期,然后将日期传递给 $match。
  • @Splitty 不用担心。我尝试了一些测试文档,但无法提出较小的管道阶段查询,这是我所能提供的要求。重点是您如何进行初始分组;在上面你想在项目日期分组。
  • 如果可能,您能否提供最小的测试用例(样本文档和该样本集合的预期结果),也许我们可以找到另一种方法?
  • 实际上,您对此有所了解,我在组之间添加了更多排序运算符,并且越来越接近我的需要。有mongodb小提琴吗?我注意到现在有 sqlfiddle dot com
  • @Splitty 中奖时告诉我 :-)
【解决方案2】:

感谢 @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
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-20
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2013-03-09
    • 2015-06-09
    相关资源
    最近更新 更多