插入多个文档后关闭node.js中的mongodb连接

插入多个文档后关闭node.js中的mongodb连接,node.js,mongodb,Node.js,Mongodb,有人问过这个问题,但OP接受的答案并没有回答我的特殊需要 我有一个实用程序脚本,可以向多个集合添加大量记录。实际上,它只是一个导入,使用署名读取非常大的文本文件,然后将数据插入到集合中: var MongoClient = require("mongodb").MongoClient; var fs = require("fs"); var byline = require("byline"); var inStream = fs.createReadStream("data.txt", {

有人问过这个问题,但OP接受的答案并没有回答我的特殊需要

我有一个实用程序脚本,可以向多个集合添加大量记录。实际上,它只是一个导入,使用署名读取非常大的文本文件,然后将数据插入到集合中:

var MongoClient = require("mongodb").MongoClient;
var fs = require("fs");
var byline = require("byline");

var inStream = fs.createReadStream("data.txt", { encoding: "utf8" });

var byLineStream = byline.createStream(inStream);

MongoClient.connect("mongodb://localhost:27017/test", { native_parser: true}, function(err, db) {  
    var collection = db.collection("Data");
    db.dropCollection("Data", function(err, result) {
        byLineStream.on("data", function(line) {
            var o = parseLineToObject(line);
            collection.insert(o);
        });
    });
});
建议的答案是将所有数据推送到一个数组中,然后在完成时使用一次写入和回调来关闭数据库。这不是一个好答案,因为我正在处理的文件非常大,因此会消耗大量内存

另一个类似的解决方案是使用
async
包创建函数数组,然后并行运行它们。另一个半身像,但至少它没有创造一个巨大的单一插入

所以问题是:一旦所有插入都完成,如何关闭MongoDB连接,以便脚本退出并且不挂起


我应该补充一点,我已经尝试了计数方法,在插入回调中递增一个计数器变量。这不起作用,因为在插入中的某个点,回调的执行和完成速度比插入的完成速度快,导致计数器在插入仍在进行时达到0,从而关闭数据库。

当所有行都已读取时,您应该设置一个标志:

var readAllLines = false;

byLineStream.on("end", function() {
  readAllLines = true;
});
接下来,在插入每条记录后检查该标志。但是,您还需要跟踪已读取的行数以及插入的行数,因此只有在所有行都已插入(甚至顺序错误)的情况下才能关闭数据库

把所有东西放在一起:

db.dropCollection("Data", function(err, result) {
  var lineCount     = 0;
  var readAllLines  = false;

  byLineStream.on("end", function() {
    readAllLines = true;
  });

  byLineStream.on("data", function(line) {
    lineCount++;
    var o = parseLineToObject(line);
    collection.insert(o, { w : 1 }, function() {
      if (--lineCount === 0 && readAllLines) {
        // we've read and inserted all lines
        db.close();
      }
    });
  });
});
但是,我确实认为将回调传递给
insert
(“安全模式”)比当前的解决方案要慢,您可以调用
insert
,但不要等待结果。为了加快速度,您可以在将行插入一条语句之前缓冲X行,而不是单独编写每行

类似于此(不包括行计数):


我昨晚一直在做这项工作,这也是我提出的解决方案,但它需要一个行计数器来确定写入是否已完成:
insertCount===0&&readAllLines
它将关闭与未完成写入的挂起写入的连接。我将在不同的答案中发布变体,如果您能更新您的答案以反映它,我将不胜感激。@NathanielJohnson我已经编辑了我的答案,请注意您还需要跟踪实际插入的行数:)
var buffer = [];
byLineStream.on("data", function(line) {
  buffer.push(parseLineToObject(line));
  if (buffer.length > 100 || readAllLines) {
    collection.insert(buffer, { w : 1 }, function() {
      if (readAllLines) {
        db.close();
      }
    });
    buffer = [];
  }
});
var MongoClient = require("mongodb").MongoClient;
var fs = require("fs");
var byline = require("byline");

var inStream = fs.createReadStream("data.txt", { encoding: "utf8" });

var byLineStream = byline.createStream(inStream);

MongoClient.connect("mongodb://localhost:27017/test", { native_parser: true}, function(err, db) {  
    var collection = db.collection("Data");
    db.dropCollection("Data", function(err, result) {  //I am completely replacing collection
        var insertCount = 0;
        var doneReadingFile = false;
        byLineStream.on("end",function(line) {
            doneReadingFile = true;
        });
        byLineStream.on("data", function(line) {
            var o = parseLineToObject(line);
            collection.insert(o,function(err, result) {
                insertCount--;
                if (insertCount === 0 && doneReadingFile) {
                    db.close();
                }
            });
        });
    });
});