#mongodb #node.js #mongoose
#mongodb #node.js #mongoose
Вопрос:
Прежде чем я углублюсь в свой вопрос, я хотел бы отметить, что я делаю это частично, чтобы ознакомиться с node и mongo. Я понимаю, что, вероятно, есть лучшие способы достижения моей конечной цели, но то, что я хочу извлечь из этого, — это общая методология, которая может применяться в других ситуациях.
Цель:
У меня есть CSV-файл, содержащий более 6 миллионов гео-ip записей. Каждая запись содержит в общей сложности 4 поля, а размер файла составляет примерно 180 мб.
Я хочу обработать этот файл и вставить каждую запись в коллекцию MongoDB, называемую «Блоки». Каждый «Блок» будет содержать 4 поля из csv-файла.
Мой текущий подход
Я использую mongoose для создания «блочной» модели и ReadStream для обработки файла построчно. Код, который я использую для обработки файла и извлечения записей, работает, и я могу заставить его выводить каждую запись на консоль, если захочу.
Для каждой записи в файле вызывается функция, которая создает новый объект Blocks (используя mongoose), заполняет поля и сохраняет его.
Это код внутри функции, которая вызывается каждый раз, когда строка считывается и анализируется. Переменная «rec» содержит объект, представляющий одну запись из файла.
block = new Block();
block.ipFrom = rec.startipnum;
block.ipTo = rec.endipnum;
block.location = rec.locid;
connections ;
block.save(function(err){
if(err) throw err;
//console.log('.');
records_inserted ;
if( --connections == 0 ){
mongoose.disconnect();
console.log( records_inserted ' records inserted' );
}
});
Проблема
Поскольку файл читается асинхронно, одновременно обрабатывается более одной строки, и чтение файла происходит намного быстрее, чем MongoDB может записать, поэтому весь процесс останавливается примерно на 282000 записях и достигает более 5 тыс. одновременных подключений Mongo. Это не приводит к сбою .. это просто сидит там, ничего не делая, и, похоже, не восстанавливается, и количество элементов в коллекции mongo больше не увеличивается.
То, что я ищу здесь, — это общий подход к решению этой проблемы. Как бы мне ограничить количество одновременных подключений к Mongo? Я хотел бы воспользоваться возможностью вставки нескольких записей одновременно, но мне не хватает способа регулировать поток.
Заранее благодарю вас.
Комментарии:
1. Вставьте элементы вашего блока в буфер, затем для каждой X записи выполните массовую вставку с использованием встроенного драйвера MongoDB (массовые вставки невозможны с mongoose): Block.collection.insert(документы, параметры, обратный вызов)
Ответ №1:
Это не ответ на вашу точную ситуацию импорта из файла .csv, а вместо этого при выполнении массовой вставки
-> Прежде всего, нет специальных операций «массовой» вставки, в конце концов, все это является предварительным.
-> если вы попытаетесь прочитать большой файл асинхронно, что было бы намного быстрее, чем процесс записи, тогда вам следует подумать об изменении вашего подхода, прежде всего, выясните, сколько может обработать ваша установка (или просто нажмите-n-trial).
—> После этого измените способ чтения из файла, вам не нужно читать каждую строку из файла асинхронно, научитесь ждать, используйте forEach, forEachSeries из Async.js чтобы снизить уровень чтения до уровня записи в mongodb, и все готово.
Комментарии:
1. Привет, я не пробовал Async.js но спасибо, что напомнили об этом. Я не знаю, смогу ли я в конечном итоге попробовать это в ближайшее время, поскольку это была старая проблема, но это звучит как хорошая идея. Спасибо!
Ответ №2:
Я бы попробовал опцию импорта CSV из командной строки из Mongodb — она должна делать то, что вам нужно, без необходимости писать какой-либо код
Комментарии:
1. Спасибо за ваше предложение. На самом деле я пробовал это раньше, и это отлично работает, но, как объяснено в вопросе, это было чисто упражнение по программированию, чтобы попытаться решить эту конкретную проблему на nodejs