Как быстрее вставить 1 миллион записей в MongoDb с Node JS? [Дубликат]

1

У меня есть копия и вставка для достижения 1 миллиона записей. Есть ли более быстрый способ? Я не могу использовать 100000 в for..loop. Командная строка окна 10 будет зависеть.

var MongoClient = require('mongodb').MongoClient,
    assert = require('assert');

var colName = 'students';
MongoClient.connect('mongodb://localhost:27017/school', function(err, db) {
    assert.equal(err, null);
    console.log("Successfully connected to MongoDB.");

    var collection = db.collection(colName);

    db.listCollections().toArray(function(err, collections) {
            if (err) console.log(err);

            var result = collections.some(function(coll) {
                if (coll.name == colName) {
                    return true;
                }
            });

            if (result) {
                console.log(colName+" FOUND.");
                collection.drop(function(err, delOK) {
                    if (err) throw err;
                    if (delOK) console.log(colName+" Collection deleted");
                    db.close();
                });             
            } else {
                console.log("NOT FOUND.");
                db.close();
            }
        });
});

var fc = 10000;
var counter = 0;

//create 10,000 records
function inputStudents(lastCount) {
    MongoClient.connect('mongodb://localhost:27017/school', function(err, db) {
        assert.equal(err, null);
        console.log("Successfully connected to MongoDB.");

        var collection = db.collection(colName);
        var types = ['exam', 'quiz', 'homework', 'homework'];

        var maxReq = 10000;
        var finalCount = lastCount * 10;

        // 10,000 students
        for (i = 0; i < maxReq; i++) {

            // take 10 classes
            for (class_counter = 0; class_counter < 10; class_counter ++) {
                scores = []
                    // and each class has 4 grades
                    for (j = 0; j < 4; j++) {
                        scores.push({'type':types[j],'score':Math.random()*100});
                    }

                // there are 500 different classes that they can take
                class_id = Math.floor(Math.random()*501); // get a class id between 0 and 500

                record = {'student_id':i, 'scores':scores, 'class_id':class_id};
                collection.insertOne(record, function(err, res) {
                        if (err) throw err;
                        counter++;
                        console.log("counter: "+counter);
                        if (counter == finalCount) db.close();
                    });
            }
        }   
    });
}

//wait 10 seconds, 1
setTimeout(function afterTenSeconds() {
    inputStudents(fc+counter);
}, 10000);

//wait 2m, 2
setTimeout(function afterTenSeconds() {
    inputStudents(fc+counter);
}, 2*60*1000);

//wait 4m, 3
setTimeout(function afterTenSeconds() {
    inputStudents(fc+counter);
}, 4*60*1000);

//wait 6m, 4
setTimeout(function afterTenSeconds() {
    inputStudents(fc+counter);
}, 6*60*1000);

//wait 8m, 5
setTimeout(function afterTenSeconds() {
    inputStudents(fc+counter);
}, 8*60*1000);

//wait 10m, 6
setTimeout(function afterTenSeconds() {
    inputStudents(fc+counter);
}, 10*60*1000);

//wait 12m, 7
setTimeout(function afterTenSeconds() {
    inputStudents(fc+counter);
}, 12*60*1000);

//wait 14m, 8
setTimeout(function afterTenSeconds() {
    inputStudents(fc+counter);
}, 14*60*1000);

//wait 16m, 9
setTimeout(function afterTenSeconds() {
    inputStudents(fc+counter);
}, 16*60*1000);

//wait 18m, 10
setTimeout(function afterTenSeconds() {
    inputStudents(fc+counter);
}, 18*60*1000);

Я должен скопировать и вставить для каждого из них, пробел в 2 минуты. Есть ли способ подключения обратного вызова? Я не могу позволить им работать одновременно. Я получу <1 миллион записей, потому что db.close отрубает некоторые записи.

  • 0
    Это должно пройти через NodeJS? Существуют инструменты командной строки для массовой загрузки, которые могут читать файлы CSV или JSON.
  • 0
    Учитель дал нам код в более старой версии. Я не могу запустить его с новым nodeJS. Я конвертирую его в более новую версию.

1 ответ

1

Вы можете использовать объемные вставки.

Существует два типа массовых операций:

  1. Упорядоченные массовые операции. Эти операции выполняют всю операцию в порядке и ошибки при первой ошибке записи.

  2. Неупорядоченные массовые операции. Эти операции выполняют все операции параллельно и суммируют все ошибки. Неупорядоченные массовые операции не гарантируют порядок исполнения.

Таким образом, вы можете сделать что-то вроде этого:

var MongoClient = require('mongodb').MongoClient;

MongoClient.connect("mongodb://myserver:27017/test", function(err, db) {
// Get the collection
var col = db.collection('myColl');

// Initialize the Ordered Batch
// You can use initializeUnorderedBulkOp to initialize Unordered Batch
var batch = col.initializeOrderedBulkOp();

// take 10 classes
        for (class_counter = 0; class_counter < 10; class_counter ++) {
            scores = []
                // and each class has 4 grades
                for (j = 0; j < 4; j++) {
                    scores.push({'type':types[j],'score':Math.random()*100});
                }

            // there are 500 different classes that they can take
            class_id = Math.floor(Math.random()*501); // get a class id between 0 and 500

            record = {'student_id':i, 'scores':scores, 'class_id':class_id};
  batch.insert(record);
}

// Execute the operations
batch.execute(function(err, result) {
  console.dir(err);
  console.dir(result);
  db.close();
});
});

Я имею в виду что-то вроде этого, я не выполнил код, поэтому я не уверен, что он сработает, но вы поймете, что я пытаюсь сказать.

Надеюсь это поможет!

  • 0
    Спасибо, bulk.insert очень быстро. Мой старый код получил 1:34. Новый 0:57, меньше минуты.
  • 0
    Новый тест: код становится очень медленным после 2 миллионов.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню