Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count subdocuments for each document

I'm trying to just count subdocuments in Mongo for each document.

It's easy to get documents in a collection with db.users.find().length(). I want to do something similar like db.users.projects.find().length(). How can I do this?

Edit:

The result I want is to know how many projects each user has... So something like:

{_id: 123, projects: 4}

Example user document:

{
   _id:{$oid: 123},
   username: johnsmith,
   projects: [{$oid: 456}, {$oid: 789}]
}
like image 669
sanjaypoyzer Avatar asked Jul 24 '15 19:07

sanjaypoyzer


People also ask

How does MongoDB count subdocuments?

To count the results, you need to use the $group stage and count the documents or do it at the application level. However, per my answer below, there is no need to unwind all of the sub-documents. In mongo shell the result of aggregation query is a cursor object, which has the count() method.

How do you count aggregation?

Returns as a BIGINT the number of rows in each group where the expression is not NULL . If the query has no GROUP BY clause, COUNT returns the number of table rows. The COUNT aggregate function differs from the COUNT analytic function, which returns the number over a group of rows within a window.

How do I count documents in MongoDB?

Description. n = count( conn , collection ) returns the total number of documents in a collection by using the MongoDB connection. n = count( conn , collection ,'Query', mongoquery ) returns the total number of documents in an executed MongoDB query on a collection.


2 Answers

Per @n9code, you will need the Aggregation Framework. However, you can very easily count the sub-documents with $size:

db.users.aggregate([{
  $project: {
    _id: '$_id',
    totalProjects: { $size: "$projects" }
  }
}]);

Which should return something like this:

{ "_id" : ObjectID(...), "totalProjects" : 89 }, ...

$size will return the length of the projects array for each document and $project changes the format of the documents to include totalProjects as the size of the projects array.

like image 146
EmptyArsenal Avatar answered Sep 27 '22 17:09

EmptyArsenal


It seems like you may have multiple username docs in your design, e.g.

{ username: "buzz", projects: [ list of 2 things ] }
{ username: "dan". projects: [ list of 3 things ] }
{ username: "buzz", projects: [ list of 4 things ] }

To arrive at the "grant total" of projects for each username try this:

c = db.foo.aggregate([
{$project: {
    "username": 1,
    "n": {$size: "$projects"}
}
}
, 
{$group: {
    "_id": "$username",
    "alln": {$sum: "$n"}
}
}
]);

to yield

{ "_id" : "buzz", "alln" : 6 }
{ "_id" : "dan", "alln" : 3 }
like image 41
Buzz Moschetti Avatar answered Sep 27 '22 17:09

Buzz Moschetti