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.

Note

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 that document.

The tail function 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.

To periodically check for new data, the cursor->more() statement
is also inside a loop.

#include "client/dbclient.h"usingnamespacemongo;/* * 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'. */voidtail(DBClientBase&conn,constchar*ns){BSONElementlastValue=minKey.firstElement();Queryquery=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;}BSONObjo=c->next();lastValue=o["insertDate"];cout<<o.toString()<<endl;}query=QUERY("insertDate"<<GT<<lastValue).hint(BSON("$natural"<<1));}}

The tail function performs the following actions:

Initialize the lastValue variable, which tracks the last
accessed value. The function will use the lastValue if the
cursor becomes invalid and tail needs to restart the
query. Use hint() to ensure that the query uses
the $natural order.

In an outer while(1) loop,

Query the capped collection and return a tailable cursor that
blocks for several seconds waiting for new documents