我有一个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);
});
我想知道是否可以通过只返回一个查询来保存一个查询。
有什么想法吗?或者这是最好的解决方案? 谢谢
答案 0 :(得分:1)
您可以使用条件分组,然后只进行最终项目来进行数学运算:
Transaction.aggregate(
[
{ "$group": {
"_id": null,
"totalPositive": {
"$cond": [ "$positive", "$amount", 0 ]
},
"totalNegative": {
"$cond": [ "$positive", 0, "$amount" ]
}
}},
{ "$project": {
"totalBalance": { "$subtract": [ "$totalPositive", "$totalNegative" ] }
}}
],
function(err,result) {
}
)
所以只评估是否$sum
"金额"取决于什么"积极"有true/false
的任何一个。然后在以下管道中使用$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的人提供了几个常见的示例,或者至少习惯于#34;声明的"问题解决的语法。
建议对aggregation framework进行一般性阅读,因为与基本的.find()
方法调用相比,SELECT thisfield where anotherfield = "this"
与高级SQL的每个其他排列之间的差异基本上都是SQL术语。