eded
eded

Reputation: 3948

mongodb aggregation get the total number of matched document

I have a following sample docs saved in mongogb, like:

{
    name: 'andy',
    age: 19,
    description: 'aaa aaa aaa'
}
{
    name: 'andy',
    age: 17,
    description: 'bbb bbb bbb'
}
{
    name: 'leo',
    age: 10,
    description: 'aaa aaa aaa'
}
{
    name: 'andy',
    age: 17,
    description: 'ccc ccc ccc'
}

what the pipeline should look like to get the total number of name in each of matched sets? so I can use this sum number for next pipe. the pipeline I currently have is this:

var pip = [
    {
        $match: { name: 'andy' }
    }
]

and I want to get this result like

{
    name: 'andy',
    age: 19,
    description: 'aaa aaa aaa',
    total_andy: 3
}
{
    name: 'andy',
    age: 17,
    description: 'bbb bbb bbb',
    total_andy: 3
}
{
    name: 'andy',
    age: 17,
    description: 'ccc ccc ccc',
    total_andy: 3
}

Upvotes: 0

Views: 649

Answers (2)

displayName
displayName

Reputation: 14379

I am not exactly clear as to what you want. And i don't have enough reputation to ask for that in a comment. So let me have a shot at answering. If the answer isn't what you want, clarify the question further and we'll get to it...

var term1group = {$group : 
                            {'_id' : '$name'},
                            'total_names' : {$sum : 1},
                            'ageAndDescription' : {$addToSet : {'$age', '$description'}}
                    }

var term2unwind = {$unwind : '$ageAndDescription'}

var term3project = {$project : {
                            _id : 0,
                            'name' : '_id',
                            'age' : '$ageAndDescription.age',
                            'description' : '$ageAndDescription.description',
                            'total_name' : 1
                            }

db.collection.aggregate(term1group, term2unwind, term3project);

Haven't tested but i am hopeful this will work.

Upvotes: 1

WiredPrairie
WiredPrairie

Reputation: 59763

You just need to use a $group and $sum to do a simple count. The output won't match exactly, but you could reformat it with NodeJS easily.

You apparently want to group on the three fields shown (name, age, and description). To do that, just add the fields and a field reference (using $):

  { $match: { name: 'andy' } },
  { $group: { 
         _id: { name: "$name", age: "$age", description: "$description"}, 
         count: { $sum: 1} 
       }
  }

To add the count of each group, include a $sum of 1 (for each document that matches the group).

Your output will look something like:

{ "_id" : { "name" : "andy", "age" : 17, "description" : "ccc ccc ccc" }, "count" : 1 }
{ "_id" : { "name" : "andy", "age" : 17, "description" : "bbb bbb bbb" }, "count" : 1 }
{ "_id" : { "name" : "andy", "age" : 19, "description" : "aaa aaa aaa" }, "count" : 3 }

If you used a projection with $project, you could also format the output to more closely match your original request:

{ $match: {name: 'andy' }}, 
{ $group: { _id: { name: "$name", age: "$age", description: "$description"} , 
         count: {$sum: 1}}
}, 
{ $project : { name: "$_id.name", _id: 0, age: "$_id.age", 
              description: "$_id.description", total_andy: "$count" 
             }
}

Results:

{ "name" : "andy", "age" : 17, "description" : "ccc ccc ccc", "total_andy" : 1 }
{ "name" : "andy", "age" : 17, "description" : "bbb bbb bbb", "total_andy" : 1 }
{ "name" : "andy", "age" : 19, "description" : "aaa aaa aaa", "total_andy" : 3 }

Upvotes: 0

Related Questions