I would like to create a sort of a ‘dashboard’ on a capped
collection (which is used as a log table) on my Mongo database.
This is how I create the collection:
db.createCollection( "messages", { capped: true, size: 100000 } );
I do a collection.find()
, with options tailable:true
, awaitdata:true
, and numberOfRetries:-1
(infinite retries).
What puzzles me is that I’d expect the find().each() loop to wait for new data (messages)… instead (after a few seconds) it errors out (with No more documents in tailed cursor
… :-()
This is the code I’m working with:
var mongo = require('mongodb'); mongo.MongoClient.connect('mongodb://127.0.0.1/myDb', function (err, db) { db.collection('messages', function(err, collection) { if (err) { return console.error('error in status collection:', err); } collection.find( // open tailable cursor {}, { tailable: true, awaitdata: true, numberOfRetries: -1 } ).each(function(err, doc) { if (err) { if (err.message === 'No more documents in tailed cursor') { console.log('finished!'); } else { console.error('error in messages collection:', err); } } else { if (doc) { console.log('message:', doc.message); } } }) }); });
What do I miss?
UPDATE:
Not having received any conclusive answer until now, I deduce MongoDb tailable collections
is not ready for prime time… :-(((
Sadly giving up for a more classic and robust fs logging solution…
Advertisement
Answer
You could set up subscriber function that subscribes for new MongoDB documents using the tailable find()
cursor as a node.js stream. The following demonstrates this:
// subscriber function var subscribe = function(){ var args = [].slice.call(arguments); var next = args.pop(); var filter = args.shift() || {}; if('function' !== typeof next) throw('Callback function not defined'); var mongo = require('mongodb'); mongo.MongoClient.connect('mongodb://127.0.0.1/myDb', function(err, db){ db.collection('messages', function(err, collection) { var seekCursor = collection.find(filter).sort({$natural: -1}).limit(1); seekCursor.nextObject(function(err, latest) { if (latest) { filter._id = { $gt: latest._id } } var cursorOptions = { tailable: true, awaitdata: true, numberOfRetries: -1 }; var stream = collection.find(filter, cursorOptions).sort({$natural: -1}).stream(); stream.on('data', next); }); }); }); }; // subscribe to new messages subscribe( function(document) { console.log(document); });
Source: How to subscribe for new MongoDB documents in Node.js using tailable cursor