【问题标题】:Two sums in one query一次查询中的两个总和
【发布时间】:2023-03-24 15:40:01
【问题描述】:

我有一个 mongodb(Mongoose 实体),它代表我的应用程序中的财务条目:

var mongoose = require('mongoose');
var ObjectId = mongoose.Schema.Types.ObjectId;

var transactionSchema = mongoose.Schema({

    description     : String,
    amount          : { type:Number, min:0.01, required:true }, 
    dateEntry       : { type:Date, default:Date.now }, 
    dateAdded       : { type:Date, default:Date.now }, 
    positive        : { type:Boolean, default:false }, 

    category        : { type: ObjectId, ref: 'Category' },
    user            : { type: ObjectId, ref: 'User' }

});

module.exports = mongoose.model('Transaction', transactionSchema);

我想给出我的交易余额:我的第一种方法是先计算正数的总和,然后再计算负数的总和,最后从正数中减去负数:

async.parallel({
                totalPositive: function(callback) {
                    var matcher = baseSearch;
                    matcher.positive = true;
                    Transaction.aggregate(
                        { $match: matcher },
                        { $group: {_id:null,sum:{$sum: '$amount'}} },
                        function(err,result) {
                            callback(err,result);
                        }
                    );
                },
                totalNegative: function(callback) {
                    var matcher = baseSearch;
                    matcher.positive = false;
                    Transaction.aggregate(
                        { $match: matcher },
                        { $group: {_id:null,sum:{$sum: '$amount'}} },
                        function(err,result) {
                            callback(err,result);
                        }
                    );
                }
            }, function(err, results) {
                if (err) {
                    return res.json({error:err.message});
                }
                results.balance = results.totalPositive[0].sum - results.totalNegative[0].sum;
                res.json(results);
            });

我想知道是否可以通过只返回一个正负和来保存一个查询。

有什么想法吗?或者这是最好的解决方案? 谢谢

【问题讨论】:

    标签: node.js mongodb mongoose mongodb-query aggregation-framework


    【解决方案1】:

    您可以通过条件分组来做到这一点,然后只是一个最终项目来进行数学运算:

    Transaction.aggregate(
        [
            { "$group": {
                "_id": null,
                "totalPositive": {
                    "$cond": [ "$positive", "$amount", 0 ]
                },
                "totalNegative": {
                    "$cond": [ "$positive", 0, "$amount" ]
                }
            }},
            { "$project": {
                "totalBalance": { "$subtract": [ "$totalPositive", "$totalNegative" ] }
            }}
        ],
        function(err,result) {
    
        }
    )
    

    因此,只需根据true/false 的“积极”程度来评估是否为$sum 提供“金额”。然后在下面的管道中使用$subtract 操作符。

    更好的是,只需在单个小组赛阶段将值的“符号”设置为“总和”:

    Transaction.aggregate(
        [
            { "$group": {
                "_id": null,
                "totalBalance": {
                    "$sum": {
                        "$cond": [
                             "$positive",
                             "$amount",
                             { "$subtract": [ 0, "$amount" ] }
                        ]
                    }
            }}
        ],
        function(err,result) {
    
        }
    );
    

    因此,当您可以一次性完成时,确实不需要并行查询。

    每种情况的“肉”主要在$cond 运算符这里,它充当三元运算符进行评估。链接到那里,但如果您不熟悉,那么这意味着提供“内联”if/then/else 评估的一种方式。所以有一个“测试”作为第一个参数,其中true第二个参数用于返回结果,否则false返回第三个参数。

    SQL to aggregation mapping 的文档中提供了其他示例,其中为那些习惯于 SQL 或至少习惯于解决问题的“声明性”语法的人提供了几个常见示例。

    建议对aggregation framework 进行一般性阅读,因为在SQL 术语中,与基本的.find() 方法调用相比,SELECT thisfield where anotherfield = "this" 与高级SQL 的所有其他排列之间的区别本质上是不同的。

    【讨论】:

    • 听起来不错!我还是mongodb的初学者,非常感谢,我会尝试然后接受答案!
    • @FabioB。很公平。慢慢来。我可能有点过于油嘴滑舌,当时没有提供足够的链接或额外的解释。但现在也添加了。
    • 在哪里可以添加额外的 $match ?我想只包含具有 {user:myUserId} 的交易。
    猜你喜欢
    • 2019-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    • 2018-07-16
    • 2019-08-10
    • 1970-01-01
    • 2016-08-25
    相关资源
    最近更新 更多