Node.js 如何从每个回调中取消MongoDB查询
我实现了一个小型NodeJs web服务器,它存储日志条目并为基于web的日志浏览器提供后端。web界面还提供了导出到CVS的功能,并允许用户下载CVS格式的日志。我的代码与此类似:Node.js 如何从每个回调中取消MongoDB查询,node.js,mongodb,Node.js,Mongodb,我实现了一个小型NodeJs web服务器,它存储日志条目并为基于web的日志浏览器提供后端。web界面还提供了导出到CVS的功能,并允许用户下载CVS格式的日志。我的代码与此类似: this.log_entries(function(err, collection) { collection.find(query) .sort({_id: 1}) .each(function (err, doc) { if(doc){
this.log_entries(function(err, collection) {
collection.find(query)
.sort({_id: 1})
.each(function (err, doc) {
if(doc){
WriteLineToCSVFile(doc);
}
else {
ZipCSVFileAndSendIt();
}
});
});
如果用户没有为查询指定正确的筛选器,则导出操作可能会占用大量时间和磁盘空间。我需要实现一个故障安全机制来防止这种情况。一个重要的要求是,用户应该能够在任何时间点中止正在进行的导出操作。目前我的解决方案是,我停止将数据写入CSV文件,但是回调传递给。每个仍会被调用。我找不到任何关于如何停止每个循环的信息。所以问题是我该怎么做
更新,答案是:
使用cursor.nextObject
有关正确答案,请参见下面@dbra的评论:db.currentOp和db.killOp不适用于这种情况
最终的解决方案如下所示:
this.log_entries(function(err, collection) {
var cursor = collection.find(query);
cursor.sort("_id", 1, function(err, sorted) {
function exportFinished(aborted) {
...
}
function processItem(err, doc) {
if(doc === null ) {
exportFinished(false);
}
else if( abortCurrentExport ) {
exportFinished(true);
}
else {
var line = formatCSV(doc);
WriteFile(line);
process.nextTick(function(){
sorted.nextObject(processItem);
});
}
}
sorted.nextObject(processItem);
});
});
注意process.nextTick的用法-如果没有它,将出现堆栈溢出 您可以使用搜索正在运行的查询,然后使用终止查询,但il将是一个令人讨厌的解决方案
一个更好的方法是处理有限的后续批次;更简单的方法是使用limit和skip进行简单的分页,但这取决于您在读取集合时如何更改。奇怪的是,db.currentOp没有显示任何正在运行的内容。可能是因为查询本身没有运行,只是光标,但可能是我错了。关于限制和跳过-我认为这会减慢速度,因为这些操作非常慢。如果分页不适用,并且操作没有显示,那么看起来只是获取的问题,因此,您可以通过在cursor.next上循环来切换到迭代方法,而不是使用批量函数forEach:然后您可以随时停止抓取循环。您还可以调整传输的块大小cursor.batchSize.Thank@dbra!使用cursor.nextObject是个好主意。现在一切正常!