【问题标题】:Aggregate by all days of month mongodb按月份的所有日期聚合 mongodb
【发布时间】:2020-05-23 14:12:34
【问题描述】:

嘿,我需要按天获取所有 totalPrice 组的总和

我得到了这个结果

但我需要获取一个月的所有休息日,即使它返回 0

我需要解决方案 这是我的代码

Order.aggregate([
    { $project: { yearMonthDay: { $dateToString: { format: "%Y-%m-%d", date: '$created' }}, totalPrice:"$totalPrice" }},
    { $group: { _id: "$yearMonthDay", count: { $sum: 1 }, total: {"$sum": "$totalPrice"} }},
    { $sort: { _id: -1 } },
    { $group: { _id: null, stats: { $push: "$$ROOT" }}}, 
    {
        $project: {
             results: {
                $map: {
                    input:{ $range:[16,31] },
                    as: 'day',
                    in: {
                        $let: {
                            vars: {
                                dateIndex: {
                                    "$indexOfArray": ["$stats._id", {$dateToString:{ date:{$dateFromParts:{'year':2020, 'month':5, 'day':"$$day"}}, format:'%Y-%m-%d'}}]
                                }
                            },
                            in: {
                                $cond: {
                                    if: { $ne: ["$$dateIndex", -1] },
                                    then: { $arrayElemAt: ["$stats", "$$dateIndex"] },
                                    else: { _id: {$dateToString:{ date:{$dateFromParts:{'year':2020, 'month':5, 'day':"$$day"}}, format:'%Y-%m-%d'}, count: 0, total: 0 } }

                                }
                            }
                        }
                    }
                }
            }
        }
    }, 
    { $unwind: "$results" },
    { $replaceRoot: { newRoot: "$results"}}
]

【问题讨论】:

  • 这能回答你的问题吗? Fill missing dates in records
  • 我什么都不懂,我认为这不一样我有我需要的 totalprice 变量,即使总价为 0
  • 你能发布预期的结果吗?它应该返回什么(2020-05-162020-05-152020-05-142020-05-13,...)?

标签: mongodb mapreduce mongodb-query aggregation-framework aggregate


【解决方案1】:

这个查询应该适合你。

db.collectionName.aggregate([
{ $project: { yearMonthDay: { $dateToString: { format: "%Y-%m-%d", date: '$created' }}, totalPrice:"$totalPrice" }},
{ $group: { _id: "$yearMonthDay", count: { $sum: 1 }, total: {"$sum": "$totalPrice"} }},
{ $sort: { _id: -1 } },
{ $group: { _id: null, stats: { $push: "$$ROOT" }}, 
{
    $project: {
        results: {
            $map: {
                input: ["2020-05-16","2020-05-15","2020-05-14","2020-05-13","2020-05-12"],
                as: "date",
                in: {
                    $let: {
                        vars: {
                            dateIndex: {
                                "$indexOfArray": ["$stats._id", "$$date"]
                            }
                        },
                        in: {
                            $cond: {
                                if: { $ne: ["$$dateIndex", -1] },
                                then: { $arrayElemAt: ["$stats", "$$dateIndex"] },
                                else: { _id: "$$date", count: 0, total: 0 }
                            }
                        }
                    }
                }
            }
        }
    }
}, 
{ $unwind: "$results" },
{ $replaceRoot: { newRoot: "$results"}}
])

前 3 个步骤与您的相同。

{ $group: { _id: null, stats: { $push: "$$ROOT" }} 会将前一个阶段的结果推送到一个数组stats 中,我们将在后面阶段使用它来查找。

在最后阶段,我们将创建可能的日期范围并对其进行迭代。 范围内的每个键。

"$indexOfArray": ["$stats._id", "$$date"] 将检查日期是否存在于stats 数组中

然后我们将使用该索引从 stats 数组中获取值,否则推送默认值。

由于这些结果仍在results 下,我们将unwind 该数组移动到root

如果您的服务器版本高于 3.6, 我们也可以简化日期范围创建部分。让我们使用 $range 将输入数组初始化为天。

input:{ $range:[16,31] },
as: 'day'

并像这样修改dateIndex 部分

dateIndex: {
   "$indexOfArray": ["$stats._id", {$dateToString:{ date:{$dateFromParts:{'year':2020, 'month':5, 'day':"$$day"}}, format:'%Y-%m-%d'}]
}

并同样更改默认值部分。

else: { _id: {$dateToString:{ date:{$dateFromParts:{'year':2020, 'month':5, 'day':"$$day"}}, format:'%Y-%m-%d'}}, count: 0, total: 0 }

或者或者,我们也可以使用concat来生成密钥

dateIndex: {
   "$indexOfArray": ["$stats._id", {$concat:["2020-05","-", {$convert:{input:"$$day", to:"string"}}]}]
}

//和默认值

else: { _id: {$concat:["2020-05","-", {$convert:{input:"$$day", to:"string"}}]}, count: 0, total: 0 }

同样,您也可以运行另一个循环数月。

【讨论】:

  • 谢谢,但是当我更改日期范围“errmsg”时出现问题:“使用未定义变量:日期”,
  • @AdelStiti 如果日期范围在同一个月内,$range 方法会有所帮助。
  • 我有这个错误 "errmsg": "Use of undefined variable: date", "code": 17276,
  • @AdelStiti 那是因为这里的else: { _id: "$$date", count: 0, total: 0 } 变量应该是$$day,因为你使用day 作为变量。我也更新了答案。 :)
  • 感谢 concat 的工作,但返回第一个解决方案“errmsg”的问题:“表示表达式的对象必须有一个字段:{ $dateToString: { date: { $dateFromParts: { year: 2020, month: 5, day: \"$$day\" } }, format: \"%Y-%m-%d\" }, count: 0, total: 0 } 我编辑了最新的查询
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-19
  • 2021-07-16
  • 2018-04-25
  • 2013-11-25
  • 1970-01-01
  • 2013-09-12
  • 2019-05-17
相关资源
最近更新 更多