如何从.each回调中取消MongoDB查询

时间:2015-08-31 08:32:07

标签: 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){
              WriteLineToCSVFile(doc);
            }
            else {
              ZipCSVFileAndSendIt();
            }
        });
});

如果用户未为查询指定正确的过滤器,则导出操作可能会占用大量时间和磁盘空间。我需要实现一个防止这种情况的故障安全机制。一个重要的要求是用户应该能够在任何时间点中止正在进行的出口操作。目前我的解决方案是我停止将数据写入CSV文件,但传递给.each()的回调仍然被调用。我找不到任何关于如何停止每个循环的信息。所以问题是我该怎么做?

更新,答案: 使用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的用法 - 没有它会有堆栈溢出!

1 个答案:

答案 0 :(得分:0)

您可以使用db.currentOp搜索正在运行的查询,然后使用db.killOp将其终止,但il会是一个讨厌的解决方案。

更好的方法是使用有限的后续批次;更简单的方法是使用“限制”和“跳过”进行简单的分页,但这取决于您在阅读时如何更改集合。