NodeJS записывает в MongoDB только один раз

#node.js #mongodb

#node.js #mongodb

Вопрос:

У меня есть приложение NodeJS, которое должно генерировать множество наборов данных синхронно (несколько вложенных циклов for). Предполагается, что эти наборы данных будут сохранены в моей базе данных MongoDB для более эффективного последующего поиска.

Я использую mongodb — драйвер для NodeJS и запускаю демон. Подключение к БД работает нормально, и, согласно окну демона, первая группа наборов данных успешно сохраняется. Каждые ~ 400-600 мс сохраняется другая группа, но после первого набора данных в консоли MongoDB больше нет выходных данных (даже ошибок), и поскольку размеры файлов не увеличиваются, я предполагаю, что эти операции записи не работают (я не могу дождаться их завершения, поскольку это займетнесколько дней до полного запуска).

Если я перезапущу скрипт NodeJS, он даже не сохранит первый ключ, возможно, из-за дубликатов? Если я удалю содержимое папки db, первое содержимое будет сохранено снова.

Это важная часть моего скрипта, и я не смог найти ничего, что я сделал неправильно. Я предполагаю, что проблема больше во внутренней логике (странные повторяющиеся проверки / не выполняется одновременно и т.д.).

 var MongoClient = require('mongodb').MongoClient, dbBuffer = [];
MongoClient.connect('mongodb://127.0.0.1/loremipsum', function(err, db) {
    if(err) return console.log("Cant connect to MongoDB");
    var collection = db.collection('ipsum');
    console.log("Connected to DB");

    for(var q=startI;q<endI;q  ) {
        for(var w=0;w<words.length;w  ) {
            dbBuffer.push({a:a, b:b});
        }
        if(dbBuffer.length) {
            console.log("saving " dbBuffer.length " items");
            collection.insert(dbBuffer, {w:1}, function(err, result) {
                if(err) {
                    console.log("Error on db write", err);
                    db.close();
                    process.exit();
                }
            });
        }
        dbBuffer = [];
    }
    db.close();
});
  

Обновить

  • db.close никогда не вызывается, и соединение не прерывается
  • Переход на массовую вставку ничего не меняет
  • Обратный вызов для вставки никогда не вызывается — это может быть проблемой! Консоль MongoDB сообщает мне, что процесс вставки прошел успешно, но похоже, что связь между драйвером и MongoDB не работает должным образом для вставки.

Комментарии:

1. collection.insert это асинхронный вызов, поэтому ваш последний db.close() вызов выполняется до их завершения.

2. Кроме того, это хороший вариант использования для Bulk.insert (вместо взлома массива dbBuffer)

3. @JohnnyHK Как уже упоминалось, это упрощенный пример нескольких вложенных циклов, которые фактически выполняются несколько дней. Я вижу в консоли MongoDB, что соединение также не закрыто. Фелипе: Вы правы, и я попробую, но на самом деле это не должно быть большой разницей.

4. Теперь изменил код и запустил его на другой машине, та же проблема.

Ответ №1:

Я «решил» это сам. Одно из моих заблуждений заключалось в том, что каждая транзакция вставки подтверждается в консоли MongoDB, в то время как на самом деле она подтверждает только первую или если между командами проходит некоторое время. Чтобы проверить, действительно ли процесс вставки работает, нужно некоторое время запускать скрипт и ждать, пока MongoDB загрузит его в локальный файл (примерно 30-60 секунд).

Кроме того, процессы вставки были слишком быстрыми друг за другом, и MongoDB, похоже, неправильно обрабатывает это в Win10 x64. Я перешел из буфера массива во внутренний буфер (см. Комментарии) и продолжил процесс только после вставки предыдущих данных.

Это упрощенный результирующий код

 db.collection('seedlist', function(err, collection) {
    syncLoop(0,0, collection);
    //...
});

function syncLoop(q, w, collection) {
    batch = collection.initializeUnorderedBulkOp({useLegacyOps: true});
    for(var e=0;e<words.length;e  ) {
        batch.insert({a:a, b:b});
    }
    batch.execute(function(err, result) {
        if(err) throw err;
        //...
        return setTimeout(function() {
            syncLoop(qNew,wNew,collection);
        }, 0); // Timer to prevent Memory leak
    });
}