I have a collection where every document in the collection has an array named foo that contains a set of embedded documents. Is there currently a trivial way in the MongoDB shell to count how many instances are within foo? something like:

db.mycollection.foos.count() or db.mycollection.foos.size()?

Each document in the array needs to have a unique foo_id and I want to do a quick count to make sure that the right amount of elements are inside of an array for a random document in the collection.

Solution 1

In MongoDB 2.6, the Aggregation Framework has a new array $size operator you can use:

> db.mycollection.insert({'foo':[1,2,3,4]})
> db.mycollection.insert({'foo':[5,6,7]})

> db.mycollection.aggregate([{$project: { count: { $size:"$foo" }}}])
{ "_id" : ObjectId("5314b5c360477752b449eedf"), "count" : 4 }
{ "_id" : ObjectId("5314b5c860477752b449eee0"), "count" : 3 }

Solution 2

if you are on a recent version of mongo (2.2 and later) you can use the aggregation framework.

db.mycollection.aggregate([
  {$unwind: '$foo'},
  {$group: {_id: '$_id', 'sum': { $sum: 1}}},
  {$group: {_id: null, total_sum: {'$sum': '$sum'}}}
])

which will give you the total foos of your collection.

Omitting the last group will aggregate results per record.

Solution 3

Using Projections and Groups

db.mycollection.aggregate(
    [
        {
            $project: {
                _id:0,
                foo_count:{$size:"$foo"},
            }
        }, 
        {
            $group: {
                foo_total:{$sum:"$foo_count"},
            }
        }
    ]
)

Multiple child array counts can also be calculated this way

db.mycollection.aggregate(
    [
        {
            $project: {
                _id:0,
                foo1_count:{$size:"$foo1"},
                foo2_count:{$size:"$foo2"},
            }
        }, 
        {
            $group: {
                foo1_total:{$sum:"$foo1_count"},
                foo2_total:{$sum:"$foo2_count"},
            }
        }
    ]
)