Как загрузить всю коллекцию с более чем 500k записей в виде csv с nodejs из mongodb?

Я пробовал это с пакетом npm под названием json2csv. Он работает нормально для записей до 75 000. Когда данных больше этого, я не получаю никакого ответа от функции обратного вызова exporttocsv, как указано ниже.

const json2csv = require('json2csv').parse;
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1; //January is 0!
var yyyy = today.getFullYear();
if (dd < 10) {
  dd = '0' + dd;
} 
if (mm < 10) {
  mm = '0' + mm;
} 
var today = dd + '_' + mm + '_' + yyyy;



router.put('/mass_report', (req, res) => {

    mass_data_download();
    res.json("Mass report download initiated");

});

function exporttocsv(data,name, callback) {
    /* Start: Json to xlsx conversion */
    if (!fs.existsSync('./csv/'+today+'/')) {
        fs.mkdirSync('./csv/'+today+'/');
    }

    var csv = json2csv(data);

    var fname = './csv/'+today+'/' +name+ new Date().getTime() + '.csv';
    fs.writeFileSync(fname, csv, 'binary',(error,response)=>{
        console.log(error);
        console.log(response);
    });
    callback(fname);

}

function mass_data_download(){


    db.collection('mass_data').aggregate([
        {$match:{
            created_on: {
                $gte: new Date("2017-09-01T00:00:00.000Z"),
            }
        }}

    ]).sort({_id:-1}).toArray( function (error, response) {
    if(error){
        console.log(error)
    }
    else{
        console.log(response.length);
        exporttocsv(response,'mass_report', function (fname) {

            console.log('reports download complted');



        })

    }

        })
}

Есть ли ограничения при экспорте данных в CSV? или как этого добиться с любыми другими альтернативами?

1 ответ

Дело в том, что вы обрабатываете огромное количество данных в памяти одновременно. Вы должны избегать этого любой ценой. Node.js идеально подходит для использования потоков, совмещенных с ним. Считайте Mongo своим читаемым потоком, затем перенаправьте его в поток преобразования json2csv и сделайте с результатом то, что вы хотите, возможно, вы захотите передать его потоку, доступному для записи, такому как файл или даже ответ http.

Mongoose поддерживает потоковую передачу. Более подробную информацию вы можете найти здесь. Json2csv также поддерживает потоковый интерфейс. здесь больше информации о потоковом API json2csv.

ОБНОВЛЕНО: конечный псевдокод должен выглядеть так:

const csv = fs.createWriteStream('file.csv');

Model.find()
    .cursor()  // read more [here][1] 
    .pipe(json2csvTransformStream) // read more in json2csv transform stream API
    .pipe(csv); // read more in fs.createWritableStream

Трубопровод будет обрабатывать весь поток потока, и вы не будете беспокоиться об утечках памяти или производительности.

Другие вопросы по тегам