Mongodb Append aggregation for optional $ match pipe operator

I am using nodejs + mongoosejs with mongodb 2.6. I have a static function on a model that sums the value of all items in a collection. Each item is assigned to a project using the projectNo property. I need a static function to give me the total for the collection, and if a projectNo argument is passed, add the $ match coding operator to the aggregation. This saves me from having to do 2 static functions that essentially do the same thing.

To tweak things up a bit, I use the bluebird's promisifyAll method to ensure that the aggregation framework returns a promise.

my static function that sums the entire collection:

db.collection.aggregateAsync([ {$group:{_id: null, amount: { $sum: "$amount" }}} ])

my static function that only summarizes the records with the corresponding projectNo:

db.collection.aggregateAsync([ {$match: { projectNo: projectNo }}, {$group:{_id: null, amount: { $sum: "$amount" }}} ])

I really want to use the Aggregate.append method to add the $ match pipeline only if req.params.projectNo is included.

When I try to add it to the asynchronous aggregation it gets an error, which makes sense because it's just a promise. If I try this:

db.collection.aggregateAsync([ {$group:{_id: null, amount: { $sum: "$amount" }}} ]).then(function(aggregate){ aggregate.append({$match: { projectNo: projectNo }}) })

I am getting an error (append is undefined). How should I do it? Or just live with the fact that I have two functions that do the same thing?

+3


source to share


1 answer


I read the source code in mongodb to see how to use the aggregate.append method. If you create aggregations using chained methods, you can use append to add any pipeline operations.

So, instead, I put an array of aggregation pipelines into an array. If there is project #, then I add the $ match pipeline to the array using unshift (). I used unshift because you usually want the $ match pipeline to limit the number of records first and then do the rest of the pipeline.



var pipeline = [{$group:{_id: null, amount: { $sum: "$amount" }}}];
if(req.params.projectNo){
    pipeline.unshift({$match: { projectNo: req.params.projectNo }});
}
db.collection.aggregateAsync(pipeline);

      

I usually make things more complicated than I need to ...

+2


source







All Articles