【问题标题】:Calculate $sum with default value使用默认值计算 $sum
【发布时间】:2017-10-05 12:37:32
【问题描述】:

我想计算每次特定通话的总支出。

我正在收集具有特定 callId 的订单,然后从结果中汇总 totalPrice 属性。

它有效,除非没有订单,否则我会得到一个空数组。我想将 0 作为 totalSpending 的默认值。

这是我的查询:

Order.aggregate({
    $match: { callId: mongoose.Types.ObjectId(callId) }
}, {
    $group: { _id: null, totalSpending: { $sum: '$totalPrice' } }
})

如果没有订单,我会得到一个空数组,如果至少有 1 个订单,我会得到[ { _id: null, totalSpending: 50 } ]

【问题讨论】:

  • 按顺序评估聚合管道。您可以只查找空数组并将 totalSpending 返回为 0
  • 这可能在聚合内部吗?

标签: node.js mongodb mongoose


【解决方案1】:

你可以试试这样的。

$project$cond 一起使用,而不是$match。这会将不匹配的 callId 文档 totalPrice 覆盖为 0。

 Order.aggregate({
    $project: {
        totalPrice: {
            $cond: [{
                $eq: ["$callId", mongoose.Types.ObjectId(callId)]
            }, "$totalPrice", 0]
        }
    }
 }, {
    $group: {
        _id: null,
        totalSpending: {
            $sum: '$totalPrice'
        }
    }
 })

【讨论】:

    【解决方案2】:

    我猜你需要一个 $ifNull 子句,如果它为 null 则返回总价,否则返回 0;

    Order.aggregate({
        $match: { callId: mongoose.Types.ObjectId(callId) }
    }, {
        $group: { _id: null, totalSpending: { 
            $sum: { 
                    $ifNull: ['$totalSpending', 0] 
                }
        }
    })
    

    【讨论】:

    • 仍然得到一个空数组。问题是,如果 $match 没有返回任何结果,则根本不会调用 $group 管道。
    • 你可以使用collection.count来检查它是否存在并且订单数不为0。如果是,那么你可以将totalSpending数组返回为0。如果计数大于 0,则可以进行上述聚合。
    • 是的,但这需要额外的查询。我想在 1 个查询中完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-15
    • 2018-10-29
    • 2021-07-01
    • 1970-01-01
    • 2012-08-23
    • 2020-10-14
    • 1970-01-01
    相关资源
    最近更新 更多