Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Populate + Aggregate in Mongoose [duplicate]

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'
      }
    }
  }
])

Question

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?

Edit

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
  }
});
like image 856
Guilherme Avatar asked Sep 25 '15 19:09

Guilherme


People also ask

Is aggregate faster than find?

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.

What does Mongoose aggregate return?

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.

What is the use of populate in mongoose?

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.


1 Answers

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
        });
    });
like image 71
Thomas Bormans Avatar answered Oct 02 '22 17:10

Thomas Bormans