在NodeJS中的MongoDB中插入一个大的csv文件,200&#39,000行+

时间:2017-01-25 17:36:41

标签: node.js mongodb csv parsing async.js

我试图解析并将一个大的csv文件插入到MongoDB中,但是当文件扩展到100行时,我得到了来自服务器的错误响应。我需要插入的文件通常超过200行和5000行。

我已经尝试了批量插入(insertMany)和Babyparse(Papaparse)流方法来逐行插入文件。但效果不佳。

节点api:

router.post('/csv-upload/:id', multipartMiddleware, function(req, res) {

    // Post vartiables
    var fileId = req.params.id;
    var csv = req.files.files.path;

    // create a queue object with concurrency 5
    var q = async.queue(function(row, callback) {
        var entry = new Entry(row);
        entry.save();
        callback();
    }, 5);

    baby.parseFiles(csv, {
        header: true, // Includes header in JSON
        skipEmptyLines: true,
        fastMode: true,
        step: function(results, parser) {
            results.data[0].id = fileId;

            q.push(results.data[0], function (err) {
                if (err) {throw err};
            });
        },
        complete: function(results, file) {
            console.log("Parsing complete:", results, file);
            q.drain = function() {
                console.log('All items have been processed');
                res.send("Completed!");
            };
        }
    });
});

此流媒体方法导致: POST SERVER net :: ERR_EMPTY_RESPONSE

不确定我是否正确使用async.queue。

有更好更有效的方法吗?或者我做错了什么?

Express Server:

// Dependencies
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var routes = require('./server/routes');
var mongoose = require("mongoose");
var babel = require("babel-core/register");
var compression = require('compression');
var PORT = process.env.PORT || 3000;
// Include the cluster module
var cluster = require('cluster');

mongoose.connect(process.env.MONGOLAB_URI || 'mongodb://localhost/routes');

  // Code to run if we're in the master process
 if (cluster.isMaster) {

    // Count the machine's CPUs
    var cpuCount = require('os').cpus().length;

    // Create a worker for each CPU
    for (var i = 0; i < cpuCount; i += 1) {
        cluster.fork();
    }

 // Code to run if we're in a worker process
 } else {
    // Express
    var app = express();

    app.use(bodyParser.json({limit: '50mb'}));
    app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));

    // Compress responses
    app.use(compression());

    // Used for production build
    app.use(express.static(path.join(__dirname, 'public')));

    routes(app);

    // Routes
    app.use('/api', require('./server/routes/api'));

    app.all('/*', function(req, res) {
        res.sendFile(path.join(__dirname, 'public/index.html'));
    });

    // Start server
    app.listen(PORT, function() {
        console.log('Server ' + cluster.worker.id + ' running on ' + PORT);
    });
}

1 个答案:

答案 0 :(得分:4)

处理导入:

很棒的问题,根据我的经验,将csv插入mongo的最快方法是通过命令行:

mongoimport -d db_name -c collection_name --type csv --file file.csv --headerline 

我不相信猫鼬有办法打电话给mongoimport(如果我错了,有人会纠正我)

但直接通过节点调用很简单:

var exec = require('child_process').exec;
var cmd = 'mongoimport -d db_name -c collection_name --type csv --file file.csv --headerline';

exec(cmd, function(error, stdout, stderr) {
  // do whatever you need during the callback
});

上述内容必须修改为动态,但应该是不言自明的。

处理上传:

从前端客户端上传文件是另一项挑战。

如果你向服务器发出请求并且在60秒内没有收到回复(大概是你上面提到的那样),大多数浏览器都会超时

一个解决方案是打开套接字连接(在npm中搜索socket.io)以获取详细信息。这将创建与服务器的持续连接,并且不受超时限制的约束。

如果上传不是问题,并且超时是由于解析/插入速度慢导致的,那么一旦实施上述内容,您可能不必担心这一点。

其他注意事项:

我不确定您需要将哪些内容发送回用户,或者需要进行哪些解析。但是,这可以在正常的请求/响应周期之外完成,或者可以在套接字连接期间处理,如果在一个请求/响应周期中需要它。