- Examples
- Using a Tailable Cursor
Using a Tailable Cursor
MongoDB offers the option to watch a capped collection for changes using a tailable cursor.
The code below “tails” the capped collection and outputs documents to the console as they are added. The method also handles the possibility of a dead cursor by tracking the field insertDate
. New documents are added with increasing values of insertDate
.
Note
Even though we are using BsonDocument
below, it is possible to use an application defined class by replacing the BsonDocument
references with that of your application defined class.
private static async Task TailCollectionAsync(IMongoCollection<BsonDocument> collection)
{
// Set lastValue to the smallest value possible
BsonValue lastValue = BsonMinKey.Value;
var options = new FindOptions<BsonDocument>
{
// Our cursor is a tailable cursor and informs the server to await
CursorType = CursorType.TailableAwait
};
// Initially, we don't have a filter. An empty BsonDocument matches everything.
BsonDocument filter = new BsonDocument();
// NOTE: This loops forever. It would be prudent to provide some form of
// an escape condition based on your needs; e.g. the user presses a key.
while (true)
{
// Start the cursor and wait for the initial response
using (var cursor = await collection.FindAsync(filter, options))
{
// This callback will get invoked with each new document found
await cursor.ForEachAsync(document =>
{
// Set the last value we saw
lastValue = document["insertDate"];
// Write the document to the console.
await Console.WriteLineAsync(document.ToString());
});
}
// The tailable cursor died so loop through and restart it
// Now, we want documents that are strictly greater than the last value we saw
filter = new BsonDocument("$gt", new BsonDocument("insertDate", lastId));
}
}
Note
If multiple documents might have the exact same insert date, then using the above logic might cause you to miss some documents in the event that the cursor gets restarted. To solve this,
you could track all the documents you’ve seen by their identifiers for the same lastValue
and ignore them in the callback. In addition, you would need to change the $gt
condition to $gte