产卵mongoinsert

时间:2014-03-06 15:04:11

标签: node.js mongodb

我的目标是插入非常大的csv,所以不要像我这样使用csv流:

            var myCollection = db.collection(myCollectionId);

            var q = async.queue(Collection.insert.bind(myCollection), 10);

            csv()
            .from.path(myFilePath, {columns: true}) 
            .transform(function(data, index, cb){

                    q.push(data, function (err, res) {
                        if (err) return cb(err);
                        cb(null, res[0]);
                    });

            })
            .on('end', function () {

                q.drain = function() { 

                       //do some stufff
                };

            })
            .on('error', function (err) {
                res.end(500, err.message);
                console.log('on.error() executed');
            });

        });

但是当文件变得非常大,比如70M +并且它们正在流式传输时,我的服务器非常慢并且需要永远,当我尝试在网站上加载页面时,它在这个过程中变得昏昏欲睡。

为什么不能像这样使用cron-job执行mongo插入。我问,因为相同的插入距离mongo命令行可能需要30秒。

P.S。不要介意readFile和lines部分,我这样做是因为我想测试在流程启动后所有行都插入到集合中的时间(尚未实现)。

var cronJob = require('cron').CronJob;
var spawn = require('child_process').spawn; 
var fs = require('fs');
function MongoImportEdgeFile(dataID, filePath){

var scriptPath = "/local/main/db/mongodb-linux-x86_64-2.4.5/bin/mongoimport";
console.log("script path = "+scriptPath)
var output = "";

 fs.readFile(filePath, 'utf-8',function(err, data) {

        if (err){
            console.log(err)
            throw err;
        }

        //console.log('data = '+data);
        var lines = data.split('\n');
        console.log("total lines in file = " + lines);

        var job = new cronJob(new Date(), function() {
            // store reference to 'this', which is cronJob object.  needed to stop job after script is done executing.
            var context = this;

            // execute R script asynchronously
            var script = spawn(scriptPath, [" -d mydb -c Data_ForID_" + dataID + " --file " + filePath + " --type csv" ]);
            console.log("Executing R script via node-cron: " + scriptPath);

            // script has finished executing, so complete cron job and fire completion callback
            script.on('close', function() {
                console.log('inside script.on(close, function() for import');
                context.stop();
            });
        }, function() {
            // callback function that executes upon completion
            console.log("Finished executing import");

        }, true);

   });

}

2 个答案:

答案 0 :(得分:1)

您不应该使用个别insert来电。您强制mongo与每次通话执行内部同步 - 我认为鉴于您的并行方法,情况会更糟。

使用bulk insertion:只需使用insert()致电array即可。

答案 1 :(得分:0)

您可以通过创建mongoimport直接从节点执行child processHere's an article on using mongoimport to import a csv。您也可以json

不知怎的,我错过了在cron中使用mongoimport的部分。如果我理解正确,你看起来好像知道要导入的csv,并且你正在使用cron来检查它们。

您是否考虑过邮件队列?这将允许您的处理器立即接收导入作业,而不是间隔。这也会限制你的处理。

如果需要更多吞吐量,可以创建附加到同一队列的其他侦听器进程。他们将竞争下一份工作。这将使您的解决方案得以扩展。