在深入探讨我的问题之前,我想指出我这样做部分是为了熟悉 node 和 mongo。我意识到可能有更好的方法来实现我的最终目标,但我想从中得到一种可能适用于其他情况的通用方法。
目标:
我有一个包含 6 多万条地理 IP 记录的 csv 文件。每条记录共包含 4 个字段,文件大小约为 180mb。
我想处理这个文件并将每条记录插入一个名为“Blocks”的 MongoDB 集合中。每个“ block ”将包含 csv 文件中的 4 个字段。
我目前的做法
我正在使用 mongoose 创建一个“ block ”模型和一个 ReadStream 来逐行处理文件。我用来处理文件和提取记录的代码有效,如果我愿意,我可以让它将每条记录打印到控制台。
对于文件中的每条记录,它调用一个函数来创建一个新的 Blocks 对象(使用 mongoose),填充字段并保存它。
这是函数内部的代码,每次读取和解析一行时都会调用它。 “rec”变量包含一个代表文件中单个记录的对象。
block = new Block();
block.ipFrom = rec.startipnum;
block.ipTo = rec.endipnum;
block.location = rec.locid;
connections++;
block.save(function(err){
if(err) throw err;
//console.log('.');
records_inserted++;
if( --connections == 0 ){
mongoose.disconnect();
console.log( records_inserted + ' records inserted' );
}
});
问题
由于文件是异步读取的,同时处理多行,读取文件的速度比 MongoDB 的写入速度要快得多,因此整个过程停滞在 282000 条记录左右,并发 Mongo 高达 5k+连接。它不会崩溃.. 它只是坐在那里无所事事而且似乎没有恢复,mongo 集合中的项目数也不会进一步增加。
我在这里寻求的是解决此问题的一般方法。我将如何限制并发 Mongo 连接的数量?我想利用能够同时插入多条记录的优势,但我缺少一种调节流程的方法。
提前谢谢你。
最佳答案
不是对您从 .csv 文件导入的确切情况的回答,而是在进行批量插入时
-> 首先没有特殊的“批量”插入操作,最后都是forEach。
-> 如果您尝试异步读取一个比写入过程快得多的大文件,那么您应该考虑改变您的方法,首先弄清楚您的设置可以处理多少,(或者只是hit-n-试验)。
---> 在那之后,改变你从文件中读取的方式,你不需要从文件中读取每一行,异步,学会等待,使用 forEach, forEachSeries from Async.js 来降低你的读取率到 mongodb 写入级别,一切顺利。
关于mongodb - 使用 nodejs 将非常大的记录集导入 MongoDB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8045838/