Question

My query looks like that:

var x = db.collection.aggregate(...);

I want to know the number of items in the result set. The documentation says that this function returns a cursor. However it contains far less methods/fields than when using db.collection.find().

for (var k in x) print(k);

Produces

_firstBatch
_cursor
hasNext
next
objsLeftInBatch
help
toArray
forEach
map
itcount
shellPrint
pretty

No count() method! Why is this cursor different from the one returned by find()? itcount() returns some type of count, but the documentation says "for testing only".

Using a group stage in my aggregation ({$group:{_id:null,cnt:{$sum:1}}}), I can get the count, like that:

var cnt = x.hasNext() ? x.next().cnt : 0;

Is there a more straight forward way to get this count? As in db.collection.find(...).count()?

Was it helpful?

Solution

Barno's answer is correct to point out that itcount() is a perfectly good method for counting the number of results of the aggregation. I just wanted to make a few more points and clear up some other points of confusion:

No count() method! Why is this cursor different from the one returned by find()?

The trick with the count() method is that it counts the number of results of find() on the server side. itcount(), as you can see in the code, iterates over the cursor, retrieving the results from the server, and counts them. The "it" is for "iterate". There's currently (as of MongoDB 2.6), no way to just get the count of results from an aggregation pipeline without returning the cursor of results.

Using a group stage in my aggregation ({$group:{_id:null,cnt:{$sum:1}}}), I can get the count

Yes. This is a reasonable way to get the count of results and should be more performant than itcount() since it does the work on the server and does not need to send the results to the client. If the point of the aggregation within your application is just to produce the number of results, I would suggest using the $group stage to get the count. In the shell and for testing purposes, itcount() works fine.

OTHER TIPS

Where have you read that itcount() is "for testing only"?

If in the mongo shell I do var p = db.collection.aggregate(...);

printjson(p.help)    

I receive

function () {
    // This is the same as the "Cursor Methods" section of DBQuery.help().
    print("\nCursor methods");
    print("\t.toArray() - iterates through docs and returns an array of the results")
    print("\t.forEach( func )")
    print("\t.map( func )")
    print("\t.hasNext()")
    print("\t.next()")
    print("\t.objsLeftInBatch() - returns count of docs left in current batch (when exhausted, a new getMore will be issued)")
    print("\t.itcount() - iterates through documents and counts them")
    print("\t.pretty() - pretty print each document, possibly over multiple lines")
}

If I do

printjson(p)

I find that

"itcount" : function (){
    var num = 0;
    while ( this.hasNext() ){
        num++;
        this.next();
    }
    return num;
}

This function

 while ( this.hasNext() ){
            num++;
            this.next();
        }

It is very similar var cnt = x.hasNext() ? x.next().cnt : 0; And this while is perfect for count...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top