Mongoose (mongodb) пакетная вставка?

Поддерживает ли Mongoose v3. 6+ пакетную вставку? Я искал несколько минут, но все, что соответствует этому запросу, - пару лет, и ответ был однозначным - нет.

Редактировать:

Для дальнейшего использования ответом будет использование Model.create(). create() принимает массив в качестве первого аргумента, поэтому вы можете передать свои документы для вставки в виде массива.

Смотрите Model.create() документацию

Ответ 1

Model.create() против Model.collection.insert(): более быстрый подход

Model.create() - плохой способ вставки, если вы работаете с очень большими объемами. Это будет очень медленно. В этом случае вы должны использовать Model.collection.insert, который работает намного лучше. В зависимости от размера Model.create(), Model.create() может Model.create() сбой! Пробовал с миллионом документов, не повезло. Использование Model.collection.insert заняло всего несколько секунд.

Model.collection.insert(docs, options, callback)
  • docs - массив документов для вставки;
  • options является необязательным объектом конфигурации - см. документацию
  • callback(err, docs) будет вызван после сохранения всех документов или возникновения ошибки. В случае успеха документы - это массив сохраняемых документов.

Как Mongoose автор указывает здесь, этот метод будет обходить любые процедуры проверки и получить доступ к драйверу Монго непосредственно. Это компромисс, который вы должны сделать, поскольку обрабатываете большой объем данных, иначе вы вообще не сможете вставить его в свою базу данных (помните, что мы говорим здесь о сотнях тысяч документов).

Простой пример

var Potato = mongoose.model('Potato', PotatoSchema);

var potatoBag = [/* a humongous amount of potato objects */];

Potato.collection.insert(potatoBag, onInsert);

function onInsert(err, docs) {
    if (err) {
        // TODO: handle error
    } else {
        console.info('%d potatoes were successfully stored.', docs.length);
    }
}

Обновление 2019-06-22: хотя insert() прежнему может использоваться просто отлично, он устарел в пользу insertMany(). Параметры точно такие же, так что вы можете просто использовать его в качестве замены для вставки, и все должно работать просто отлично (ну, возвращаемое значение немного отличается, но вы, вероятно, не используете его в любом случае).

Ссылка

Ответ 2

Mongoose 4.4.0 теперь поддерживает объемную вставку

Mongoose 4.4.0 вводит --true-- объемную вставку с модельным методом .insertMany(). Это быстрее, чем цикл на .create() или предоставление ему массива.

Использование:

var rawDocuments = [/* ... */];

Book.insertMany(rawDocuments)
    .then(function(mongooseDocuments) {
         /* ... */
    })
    .catch(function(err) {
        /* Error handling */
    });

или

Book.insertMany(rawDocuments, function (err, mongooseDocuments) { /* Your callback function... */ });

Вы можете отслеживать его:

Ответ 3

В самом деле, вы можете использовать метод "create" Mongoose, он может содержать массив документов, см. этот пример:

Candy.create({ candy: 'jelly bean' }, { candy: 'snickers' }, function (err, jellybean, snickers) {
});

Функция обратного вызова содержит вставленные документы. Вы не всегда знаете, сколько элементов нужно вставить (фиксированная длина аргумента, как указано выше), чтобы вы могли их пропустить:

var insertedDocs = [];
for (var i=1; i<arguments.length; ++i) {
    insertedDocs.push(arguments[i]);
}

Обновление: лучшее решение

Лучшим решением было бы использовать Candy.collection.insert() вместо Candy.create() - используемый в примере выше - потому что он быстрее (create() вызывает Model.save() для каждого элемента, чтобы он был медленнее).

Для получения дополнительной информации см. документацию Mongo: http://docs.mongodb.org/manual/reference/method/db.collection.insert/

(спасибо arcseldon за указание этого)

Ответ 4

Вы можете выполнить массовую вставку с использованием оболочки mongoDB, используя вставку значений в массив.

db.collection.insert([{values},{values},{values},{values}]);

Ответ 5

Вы можете выполнять массовую вставку с использованием мангуста, как самый высокий балл. Но пример не может работать, он должен быть:

/* a humongous amount of potatos */
var potatoBag = [{name:'potato1'}, {name:'potato2'}];

var Potato = mongoose.model('Potato', PotatoSchema);
Potato.collection.insert(potatoBag, onInsert);

function onInsert(err, docs) {
    if (err) {
        // TODO: handle error
    } else {
        console.info('%d potatoes were successfully stored.', docs.length);
    }
}

Не используйте экземпляр схемы для массовой вставки, вы должны использовать простой объект карты.

Ответ 6

Кажется, что при использовании мангуста существует предел более 1000 документов при использовании

Potato.collection.insert(potatoBag, onInsert);

Вы можете использовать:

var bulk = Model.collection.initializeOrderedBulkOp();

async.each(users, function (user, callback) {
    bulk.insert(hash);
}, function (err) {
    var bulkStart = Date.now();
    bulk.execute(function(err, res){
        if (err) console.log (" gameResult.js > err " , err);
        console.log (" gameResult.js > BULK TIME  " , Date.now() - bulkStart );
        console.log (" gameResult.js > BULK INSERT " , res.nInserted)
      });
});

Но это почти в два раза быстрее при тестировании 10000 документов:

function fastInsert(arrOfResults) {
var startTime = Date.now();
    var count = 0;
    var c = Math.round( arrOfResults.length / 990);

    var fakeArr = [];
    fakeArr.length = c;
    var docsSaved = 0

    async.each(fakeArr, function (item, callback) {

            var sliced = arrOfResults.slice(count, count+999);
            sliced.length)
            count = count +999;
            if(sliced.length != 0 ){
                    GameResultModel.collection.insert(sliced, function (err, docs) {
                            docsSaved += docs.ops.length
                            callback();
                    });
            }else {
                    callback()
            }
    }, function (err) {
            console.log (" gameResult.js > BULK INSERT AMOUNT: ", arrOfResults.length, "docsSaved  " , docsSaved, " DIFF TIME:",Date.now() - startTime);
    });
}

Ответ 7

Вот оба способа сохранения данных с помощью insertMany и сохранить

1) Мангуста сохранить массив документов с insertMany навалом

/* write mongoose schema model and export this */
var Potato = mongoose.model('Potato', PotatoSchema);

/* write this api in routes directory  */
router.post('/addDocuments', function (req, res) {
    const data = [/* array of object which data need to save in db */];

    Potato.insertMany(data)  
    .then((result) => {
            console.log("result ", result);
            res.status(200).json({'success': 'new documents added!', 'data': result});
    })
    .catch(err => {
            console.error("error ", err);
            res.status(400).json({err});
    });
})

2) Мангуст сохранить массив документов с помощью .save()

Эти документы сохранят параллельно.

/* write mongoose schema model and export this */
var Potato = mongoose.model('Potato', PotatoSchema);

/* write this api in routes directory  */
router.post('/addDocuments', function (req, res) {
    const saveData = []
    const data = [/* array of object which data need to save in db */];
    data.map((i) => {
        console.log(i)
        var potato = new Potato(data[i])
        potato.save()
        .then((result) => {
            console.log(result)
            saveData.push(result)
            if (saveData.length === data.length) {
                res.status(200).json({'success': 'new documents added!', 'data': saveData});
            }
        })
        .catch((err) => {
            console.error(err)
            res.status(500).json({err});
        })
    })
})

Ответ 8

Я использовал ссылку async-forEach (для документации пакета асинхронного ввода-вывода для npm) для достижения того же.

Мой фрагмент кода выглядит следующим образом. Я получаю документы в req.body.

var forEach = require('async-foreach').forEach;    
exports.save_Ctrl = function (req, res) {    
//  var l=req.body;
//  console.log("length:",l.length);

 forEach(req.body, function(item, index, object,err) {

    console.log(req.body[index]);
    var post = new saveObj(req.body[index]);   

        //save model to MongoDB
    post.save(function (err) {
        if (err) {
            console.log('error saving :' + err.message);
            return err;
        }   
        else {
            console.log("Post saved");
        }
    });       

  });    
 }

Ответ 9

Делимся рабочим и соответствующим кодом из нашего проекта:

//documentsArray is the list of sampleCollection objects
sampleCollection.insertMany(documentsArray)  
    .then((res) => {
        console.log("insert sampleCollection result ", res);
    })
    .catch(err => {
        console.log("bulk insert sampleCollection error ", err);
    });