使用nodejs在mongoDB oplog集合中查找每个新文档不起作用(游标似乎变得无效或死亡)

我想实现的想法是在创build新文档 (如插入到数据库集合中)时读取(查找)mongoDB oplog集合。

这是我的代码简化:

var MongoClient = require('mongodb').MongoClient; MongoClient.connect(url, function(err, db) { if(err){console.error("ERROR",err); return;} console.log("Connected correctly to server"); db.collection('oplog.rs').find({ ns: 'cabo_dev.documents', op: 'i', // ts: { // $gte: $gte // } }, { tailable: true }) .each(function (err, entry) { if (err) { console.error("Error fetching a document", err, entry); return; } console.log('--- entry', entry); }); }); 

我已经评论了美元的价值来简化,但这个想法是读取所有“新”日志,而不是旧的。 我也有一个类似的代码使用mongoose,而不是原始的驱动程序。

根据文档,以前的代码将返回表示插入cabo_dev.documents集合(cabo_dev是db的名称)的所有oplog文档以及所有新的后续插入。 然而,当它完成返回文档('旧'),然后没有更多的文档返回,它将返回下一个输出为错误(每个错误var):

 { [MongoError: No more documents in tailed cursor] name: 'MongoError', message: 'No more documents in tailed cursor', tailable: true, awaitData: true } 

之后,它不再从oplog获取更多的插入。 根据可读文档 ,光标死亡或无效的原因之一是:

  • 查询返回不匹配。

这是我认为在这里发生的事情。 但是,在这种情况下, 每个进程永远不会结束(当游标变得死或无效时,这是我所期待的,不是吗?)。 但我真的想继续获取后续的插入日志。

我究竟做错了什么?

可能你现在可能已经find了答案。 但是我正在写这个答案,以至于任何人在这个同样的问题上磕磕绊绊,得到解决的办法。

在我的情况下,mongodb驱动程序版本是2.0.33

在与mongodb服务器build立连接之后,请执行以下操作:

 db.collection('yourCappedColl', function (err, coll) { var stream = coll.find({}, { tailable: true, awaitdata: true, numberOfRetries: Number.MAX_VALUE }).stream(); stream.on('data', function(val) { console.log('Doc: %j',val); }); stream.on('error', function(val) { console.log('Error: %j', val); }); stream.on('end', function(){ console.log('End of stream'); }); }); 

那是:

  1. 使用stream()而不是每个()
  2. numberOfRetries设置为Number.MAX_VALUE
  3. awaitData设置为true

欲了解更多详情,请参阅这个jira项目:

MongoError:没有更多的文件在尾巴光标

@havish以前的回答是很好的,但是这是假设你可以在第一个地方停止数据库的oplog(我不能)。 如果你的mongod进程是副本集的成员,你将只能在MongoDB中做到这一点。

在你问之前,你不需要在一个集合中有多个副本,有效地使它成为一个副本集。 这就是MongoDB如何创build一个可发布的oplog数据库集合,然后您可以stream式处理。

这里有一个简单的mongod命令来在后台运行MongoDB:

 mongod --port 27017 --dbpath /data/db --logpath test.log --replSet test0 --fork 

然后,启动一个mongo shell并运行这些来初始化你的副本集:

 $ mongo localhost:27017/test > rs.initialize() > rs.slaveOK() 

然后,select你的oplogger:

  • 本地MongoClientstream
  • mongo-oplog
  • 别的东西?