首页 > 解决方案 > MongoDB按天分组,名称和金额总和

问题描述

我的文档结构示例:

    {
    name: 'John',
    amount: '450.00'
    created_date: '1542283200000'
    },
    {
    name: 'Mark',
    amount: '890.00'
    created_date: '1542851379000'
    },
    {
    name: 'Chris',
    amount: '450.00'
    created_date: '1542851379000'
    },
    {
    name: 'Jack',
    amount: '230.00'
    created_date: '1542851379000'
    }...

我想要金额的总和,按日期和名称分组。假设我通过了 from_date 和 to_date(相隔 3 天)的过滤器,我应该得到:

    {
    name: 'John', amount: '990', date: '20/11'
    },
    {
    name: 'John', amount: '200', date: '21/11'
    },
    {
    name: 'John', amount: '120', date: '22/11'
    },
    {
    name: 'Mark', amount: '323', date: '20/11'
    },
    {
    name: 'Mark', amount: '523', date: '21/11'
    },
    {
    name: 'Mark', amount: '734', date: '22/11'
    },
    {
    name: 'Chris', amount: '353', date: '20/11'
    },
    {
    name: 'Chris', amount: '744', date: '21/11'
    },
    {
    name: 'Chris', amount: '894', date: '22/11'
    },
    {
    name: 'Jack', amount: '534', date: '20/11'
    },
    {
    name: 'Jack', amount: '663', date: '21/11'
    },
    {
    name: 'Jack', amount: '235', date: '22/11'
    }

我知道 MongoDb 的基础知识,并且能够按名称获取包含组的记录聚合。我也通过这个链接,但我无法使用它,因为在这里他们使用 ISO 时间(我的有时间戳)并且只按一个属性分组。

标签: mongodb

解决方案


这里的主要困难是您将日期(时间戳)和金额都存储为字符串。所以在 MongoDB 4.0 或更高版本中可能很容易解决这个问题,因为有$toLong$toDate$toDouble运算符可用。因此,拥有时间戳,ISODate您可以使用$dateToParts为您提供日期、月份等单独的字段。然后您可以分组(day, month, name)并使用$sum来计算总金额。尝试:

db.col.aggregate([
    {
        $addFields: {
            created_date: { $dateToParts: { date: { $toDate: { $toLong: "$created_date" } } } }
        }
    },
    {
        $group: {
            _id: { 
                name: "$name",
                day: "$created_date.day",
                month: "$created_date.month"
            },
            amount: { $sum: { $toDouble: "$amount" } }
        }
    },
    {
        $project: {
            _id: 0,
            name: "$_id.name",
            amount: 1,
            date: { $concat: [ { $toString: "$_id.day" }, "/", { $toString: "$_id.month" } ] }
        }
    }
])

输出:

{ "amount" : 230, "name" : "Jack", "date" : "22/11" }
{ "amount" : 450, "name" : "Chris", "date" : "22/11" }
{ "amount" : 890, "name" : "Mark", "date" : "22/11" }
{ "amount" : 450, "name" : "John", "date" : "15/11" }

推荐阅读