【问题标题】:MongoDB group by day and name with sum of amountMongoDB按天分组,名称和金额总和
【发布时间】:2019-05-03 07:04:28
【问题描述】:

我的文档结构示例:

    {
    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 的基础知识,并且能够按名称获取包含组的记录聚合。我也经历了这个link,但我无法使用它,因为在这里他们使用 ISO 时间(我的有时间戳)并且只按一个属性分组。

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    这里的主要困难是您将日期(时间戳)和金额都存储为字符串。所以在 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" }
    

    【讨论】:

    • 完美解决方案!!我从中学到了很多。我为 from/to date 和 $sort 添加了 $match,它按我的意愿工作。谢谢。