Michael
Michael

Reputation: 16122

MongoDB aggregate count of items in array across different documents?

Here is my MongoDB collection schema:

company: String
model: String
tags: [String]

I need to aggregate it so I get the following output:

[{
  "_id": {
    "company": "Lenovo",
    "model": "T400"
  },
  "tags": {
    tag: "SomeTag"
    count: 124 // number of times, this tag was found in `Lenovo T400`
  }
}...]

I tried to do the following:

var aggParams = {};
aggParams.push({ $unwind: '$tags' });
aggParams.push({ $group: {
  _id: { company: '$company', model: '$model'  },
  tags: { $push:  { tag: '$tags', count: { $sum: 1 } } },
}});

But I got the following error:

invalid operator '$sum'

What is the right way to do this with aggregation?

Upvotes: 2

Views: 532

Answers (1)

Blakes Seven
Blakes Seven

Reputation: 50406

You need to process $unwind on an array in order to deal with it meaninfully in aggregation. Also you adding to an array and "counts" stage a separate. As well an aggregation pipeline in an "array" of arguments itself, and not an object as you have defined:

Model.aggregate([
    { "$unwind": "$tags" },
    { "$group": {
        "_id": {
            "company": "$company",
            "model": "$model",
            "tag": "$tags"
        },
        "count": { "$sum": 1 }
    }},
    { "$group": {
        "_id": { 
            "company": "$_id.company",
            "model": "$_id.model",
         },
         "tags": { "$push": { "tag": "$_id.tag", "count": "$count" }
    }}
], function(err,result) {

})

So two $group stages does the job here. One to sum up the tags within company and model and the other to group on just the "company" and "model" and add the distinct tags and counts to an array.

Upvotes: 4

Related Questions