I have two Mongoose models: one for transactions and the other one for the tags associated with them. In order to implement some reports, I need aggregate code like this:
Transaction.aggregate([
{ $unwind: '$tags' },
{
$group: {
_id: '$tags',
amount: {
$sum: '$amount'
}
}
}
])
This produces output containing _id
and amount
. Now, I'd like to populate the other fields (e.g. name
) from the model, keeping the calculated amount
column. Can I do that within a simple populate
?
The schemas for the models I'm describing:
var TransactionSchema = new Schema({
description: {
type: String,
trim: true
},
amount: {
type: Number,
required: 'Forneça um valor',
},
date: {
type: Date,
required: 'Forneça uma data',
default: Date.now
},
fromOfx: {
type: Boolean,
default: false
},
created: {
type: Date,
default: Date.now
},
correlated: {
type: Boolean,
default: false
},
tags: [{
type: Schema.Types.ObjectId,
ref: 'TransactionTag'
}],
correlates: [{
type: Schema.Types.ObjectId,
ref: 'Transaction'
}],
user: {
type: Schema.Types.ObjectId,
ref: 'User'
}
});
var TransactionTagSchema = new Schema({
name: {
type: String,
required: 'Forneça um nome',
trim: true
},
description: {
type: String,
trim: true
},
amount: {
type: Number
}
});
Aggregation wins where the volume of data returned is much less than the original data or where you don't have the skill to build fast client side aggregations. I hope it answers your query.
Returns: A cursor to the documents produced by the final stage of the aggregation pipeline operation, or if you include the explain option, the document that provides details on the processing of the aggregation operation. If the pipeline includes the $out operator, aggregate() returns an empty cursor.
Mongoose Populate() Method. In MongoDB, Population is the process of replacing the specified path in the document of one collection with the actual document from the other collection.
You can populate an aggregation after you fetched the data from the MongoDB. This will look something like this:
// Your aggregate query from your question
Transaction.aggregate([{
$unwind: '$tags'
}, {
$group: {
_id: '$tags',
amount: {
$sum: '$amount'
}
}
}])
.exec(function(err, transactions) {
// Don't forget your error handling
// The callback with your transactions
// Assuming you are having a Tag model
Tag.populate(transactions, {path: '_id'}, function(err, populatedTransactions) {
// Your populated translactions are inside populatedTransactions
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With