Cursors

Cursors

In the mongo shell, the primary method for the read operation is the db.collection.find() method. This method queries a collection and returns a cursor to the returning documents. To access the documents, you need to iterate the cursor. However, in the mongo shell, if the returned cursor is not assigned to a variable using the var keyword, then the cursor is automatically iterated up to 20 times to print up to the first 20 documents in the results.

For example, in the mongo shell, the following read operation queries the inventory collection for

documents that have type equal to ‘food’ and automatically print first 20 matching documents, as

db.inventory.find( { type: ‘food’ } );

You can use the DBQuery.shellBatchSize to change the number of iteration from the default value 20.

Closure of Inactive Cursors – By default, the server will automatically close the cursor after 10 minutes of inactivity or if client has exhausted the cursor. To override this behavior, you can specify the noTimeout wire protocol flag in your query; however, you should either close the cursor manually or exhaust the cursor. In the mongo shell, you can set the noTimeout flag:

var myCursor = db.inventory.find().addOption(DBQuery.Option.noTimeout);

Cursor Isolation – Because the cursor is not isolated during its lifetime, intervening write operations on a document may result in a cursor that returns a document more than once if that document has changed. To handle this situation, see the information on snapshot mode.

Cursor Batches – The MongoDB server returns the query results in batches. Batch size will not exceed the maximum BSON document size. For most queries, the first batch returns 101 documents or just enough documents to exceed 1 megabyte. Subsequent batch size is 4 megabytes. To override the default size of the batch, use batchSize() and limit(). For queries that include a sort operation without an index, the server must load all the documents in memory to perform the sort and will return all documents in the first batch.

As you iterate through the cursor and reach the end of the returned batch, if there are more results, cursor.next() will perform a getmore operation to retrieve the next batch. To see how many documents remain in the batch as you iterate the cursor, you can use the objsLeftInBatch() method, as in the following example

var myCursor = db.inventory.find();

var myFirstDocument = myCursor.hasNext() ? myCursor.next() : null;

myCursor.objsLeftInBatch();

Cursor Information – You can use the command cursorInfo to retrieve the following information on cursors

  • total number of open cursors
  • size of the client cursors in current use
  • number of timed out cursors since the last server restart

Consider the following example:

db.runCommand( { cursorInfo: 1 } )

The result from the command returns the following document:

{ “totalOpen” : <number>,

“clientCursors_size” : <number>,

“timedOut” : <number>,

“ok” : 1

}

Tailable Cursor – By default, MongoDB will automatically close a cursor when the client has exhausted all results in the cursor. However, for capped collections you may use a Tailable Cursor that remains open after the client exhausts the results in the initial cursor. Tailable cursors are conceptually equivalent to the tail Unix command with the -f option (i.e. with “follow” mode.) After clients insert new additional documents into a capped collection, the tailable cursor will continue to retrieve documents.

Use tailable cursors on capped collections that have high write volumes where indexes aren’t practical. For instance, MongoDB replication uses tailable cursors to tail the primary’s oplog.

If your query is on an indexed field, do not use tailable cursors, but instead, use a regular cursor. Keep track of the last value of the indexed field returned by the query. To retrieve the newly added documents, query the collection again using the last value of the indexed field in the query criteria, as in the following example

db.<collection>.find( { indexedField: { $gt: <lastvalue> } } )

Consider the following behaviors related to tailable cursors

  • Tailable cursors do not use indexes and return documents in natural order.
  • Because tailable cursors do not use indexes, the initial scan for the query may be expensive; but, after initially exhausting the cursor, subsequent retrievals of the newly added documents are inexpensive.
  • Tailable cursors may become dead, or invalid, if either:
  • the query returns no match.
  • the cursor returns the document at the “end” of the collection and then the application deletes those document.

A dead cursor has an id of 0. An C++ example involves the tail function which uses a tailable cursor to output the results from a query to a capped collection. The function handles the case of the dead cursor by having the query be inside a loop and to periodically check for new data, the cursor->more() statement is also inside a loop.

#include “client/dbclient.h”

using namespace mongo;

/*Example of a tailable cursor.

* The function “tails” the capped collection (ns) and output elements as they are added.

* The function also handles the possibility of a dead cursor by tracking the field ‘insertDate’.

* New documents are added with increasing values of ‘insertDate’.  */

void tail(DBClientBase& conn, const char *ns) {

BSONElement lastValue = minKey.firstElement();

Query query = Query().hint( BSON( “$natural” << 1 ) );

while ( 1 ) {         auto_ptr<DBClientCursor> c =

conn.query(ns, query, 0, 0, 0,

QueryOption_CursorTailable | QueryOption_AwaitData );

while ( 1 ) {

if ( !c->more() ) {  if ( c->isDead() ) { break;  }

continue;  }

BSONObj o = c->next();

lastValue = o[“insertDate”];

cout << o.toString() << endl;

}   query = QUERY( “insertDate” << GT << lastValue ).hint( BSON( “$natural” << 1 ) );

}          }

Summary – MongoDB’s query cursor methods are summarized as

NameDescription
cursor.count()Returns a count of the documents in a cursor.
cursor.explain()Reports on the query execution plan, including index use, for a cursor.
cursor.hint()Forces MongoDB to use a specific index for a query.
cursor.limit()Constrains the size of a cursor’s result set.
cursor.next()Returns the next document in a cursor.
cursor.skip()Returns a cursor that begins returning results only after passing or skipping a number of documents.
cursor.sort()Returns results ordered according to a sort specification.
cursor.toArray()Returns an array that contains all documents returned by the cursor.

MongoDB’s query and data manipulation collection methods are summarized as

NameDescription
db.collection.count()Wraps count to return a count of the number of documents in a collection or matching a query.
db.collection.distinct()Returns an array of documents that have distinct values for the specified field.
db.collection.find()Performs a query on a collection and returns a cursor object.
db.collection.findOne()Performs a query and returns a single document.
db.collection.insert()Creates a new document in a collection.
db.collection.remove()Deletes documents from a collection.
db.collection.save()Provides a wrapper around an insert() and update() to insert new documents.
db.collection.update()Modifies a document in a collection.

Apply for MongoDB Certification Now!!

https://www.vskills.in/certification/databases/mongodb-server-administrator

Back to Tutorial

Share this post
[social_warfare]
Remove Documents
Document Structure

Get industry recognized certification – Contact us

keyboard_arrow_up