Search This Blog

Friday 19 September 2014

DBCursor - size,length and count

Consider the below method:
public static String DB_NAME = "fruits";
   public static String COLLECTION_NAME = "fruits";
   public static void main(String[] args) throws UnknownHostException {
      Mongo mongoClient = new Mongo();
      DB targetDB = mongoClient.getDB(DB_NAME);

      DBCollection collection = targetDB.getCollection(COLLECTION_NAME);
      DBCursor cursor = collection.find();
      System.out.println("Count of  records are : " + cursor.count());
      System.out.println("Length of records are : " + cursor.length());
      cursor.close();

      mongoClient.close();
   }
The above code opens a cursor to the fruit collection.I ran code to get result of count and length methods of the cursor.
Count of  records are : 4
Length of records are : 4
I created a sample collection and added like a large number of  objects to the collection.
122934447 records.This is big. If I run my read code on this store now:
Count of  records are : 122934447
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
 at java.util.LinkedHashMap.createEntry(LinkedHashMap.java:442)
 at java.util.HashMap.addEntry(HashMap.java:856)
 at java.util.LinkedHashMap.addEntry(LinkedHashMap.java:427)
 at java.util.HashMap.put(HashMap.java:484)
 at org.bson.BasicBSONObject.put(BasicBSONObject.java:281)
My code crashed for the length function.
It is not that the above two methods are same. Consider the code for the two methods:
public int count() {
   if ( _collection == null )
        throw new IllegalArgumentException("why is _collection null");
   if ( _collection._db == null )
        throw new IllegalArgumentException("why is _collection._db null");
   return (int)_collection.getCount(this._query, this._keysWanted, getReadPreference());
}
and the length method:
public int length() {
  _checkType( CursorType.ARRAY );
  _fill( Integer.MAX_VALUE );
  return _all.size();
}
The count method simply returns a count of the records associated with the cursor. Length method on the other hand does some more things. The method will fetch all records from mondoDB and add it to a java array. So any next call on the cursor will not be a database hit, instead a simple fetch from the java array.
But trying to execute length function on a collection of  122934447 records meant fetching 122934447 records from the database and putting them in a java array. The result - Out of memory.
There is also a size method available in the cursor API. Like length, it counts the number of objects matching the query. The difference with the size method is that  it  takes limit/skip settings into consideration
public static void queryResultCount() throws UnknownHostException {
      Mongo mongoClient = new Mongo();
      DB targetDB = mongoClient.getDB(DB_NAME);

      DBCollection coll = targetDB.getCollection("Players");
      BasicDBObject query = new BasicDBObject();
      DBCursor cursor = coll.find(query);
      cursor.limit(10);
      System.out.println("Count of  records are : " + cursor.count());
      System.out.println("Size of  records are : " + cursor.size());
      mongoClient.close();
   }
In the above code we have applied a limit on the cursor. If we look at the execution result:
Count of  records are : 122934447
Size of  records are : 10
As seen above the result of the size method differed from that of the length method.

No comments:

Post a Comment