【问题标题】:Spawning a mongoinsert产生一个 mongoinsert
【发布时间】:2014-04-09 07:27:37
【问题描述】:

我的目标是插入非常大的 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 秒。

附:不要介意 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);

   });

}

【问题讨论】:

  • 为什么不从 child_process.exec 执行 mongoimport?
  • 嗨乔希,你是什么意思?我正在尝试在 cron 中使用 spawn

标签: node.js mongodb


【解决方案1】:

您不应使用单独的insert 调用。你强迫mongo 对每个调用执行内部同步——我认为考虑到你的并行方法,情况更糟。

使用bulk insertion:就像使用array 调用insert() 一样简单。

【讨论】:

  • 当我尝试作为文档数组插入时:
  • 当我尝试作为文档数组插入时出现错误:文档超出最大允许的 bson 大小 16777216 字节
  • 而且我已经检查了数组,所有文档的格式为 { a: 'hi', b: 'there', c: 'bye' }。当我从 100,000 到 1,000,000 时出现错误。
  • 不要单独插入每个文档,但也不要一次插入全部! Mongo 显然不是为每秒一百万次插入而设计的,也不是为单次插入 70mb 设计的。编写代码以执行一系列具有可配置最大值的批量插入,并玩弄数字直到找到足够的值
【解决方案2】:

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

不知何故,我错过了在 cron 中使用 mongoimport 的部分。如果我理解正确,您似乎以某种方式知道要导入的 csv,并且您正在使用 cron 来检查它们。

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

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

【讨论】:

  • @SOUser 我建议您在 Node.js 中执行此操作,而不是命令行。但是,我对我的答案进行了调整。
猜你喜欢
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 2012-09-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多