Inserte un archivo csv grande, 200’000 filas +, en MongoDB en NodeJS

Estoy tratando de analizar e insertar un gran archivo csv en MongoDB, pero cuando el archivo se extiende a más de 100,000 filas, recibo una mala respuesta del servidor. Y los archivos que necesito insertar están generalmente por encima de 200,000 filas.

He intentado el método de inserción masiva (insertMany) y Babyparse (Papaparse) para insertar el archivo fila por fila. Pero con malos resultados.

Nodo 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!"); }; } }); }); 

Los resultados de este enfoque de transmisión en: POST SERVER net :: ERR_EMPTY_RESPONSE

No estoy seguro si estoy usando el async.queue correctamente sin embargo.

¿Hay una forma mejor y más eficiente de hacer esto O estoy haciendo algo mal?

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); }); } 

Manejando la importación:

Buena pregunta, desde mi experiencia, la forma más rápida de insertar un csv en mongo es a través de la línea de comandos:

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

No creo que la mongoose tenga una forma de llamar a mongoimport (alguien me corrige si me equivoco)

Pero es lo suficientemente simple para llamar a través de nodo directamente:

 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 }); 

Lo anterior tendrá que ser modificado para que sea dynamic, pero debe ser autoexplicativo.

Manejando la subida:

Cargar el archivo desde un cliente de front-end es otro desafío.

La mayoría de los navegadores agotarán el tiempo de espera si realiza una solicitud a un servidor y no obtiene una respuesta en 60 segundos (probablemente a lo que se refiere anteriormente)

Una solución sería abrir una conexión de socket (buscar socket.io en npm) para obtener más información. Esto creará una conexión constante con el servidor y no estará sujeto a las restricciones de tiempo de espera.

Si la carga no es un problema, y ​​el tiempo de espera se debe al lento análisis / inserción, es posible que no tenga que preocuparse por esto una vez que implemente lo anterior.

Otras Consideraciones:

No estoy seguro de qué es exactamente lo que necesita enviar al usuario o qué análisis debe tener lugar. Pero eso puede hacerse fuera del ciclo normal de solicitud / respuesta, o puede manejarse durante una conexión de socket si es necesario durante un ciclo de solicitud / respuesta.