我试图解析并将一个大的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);
});
}
答案 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)以获取详细信息。这将创建与服务器的持续连接,并且不受超时限制的约束。
如果上传不是问题,并且超时是由于解析/插入速度慢导致的,那么一旦实施上述内容,您可能不必担心这一点。
其他注意事项:
我不确定您需要将哪些内容发送回用户,或者需要进行哪些解析。但是,这可以在正常的请求/响应周期之外完成,或者可以在套接字连接期间处理,如果在一个请求/响应周期中需要它。