web-dev-qa-db-fra.com

Mangouste (mongodb) insertion de lot?

Est-ce que Mongoose v3.6 + supporte les insertions par lots maintenant? J'ai cherché quelques minutes, mais tout ce qui correspond à cette requête date de quelques années et la réponse était un non sans équivoque.

Modifier:

Pour référence future, la solution consiste à utiliser Model.create(). create() accepte un tableau en tant que premier argument. Vous pouvez donc transmettre vos documents pour qu'ils soient insérés en tant que tableau.

Voir documentation de Model.create ()

106
Geuis

Model.create () vs Model.collection.insert (): une approche plus rapide

Model.create() est un mauvais moyen de faire des insertions si vous avez affaire à un très gros volume. Ce sera très lent . Dans ce cas, vous devriez utiliser Model.collection.insert, qui donne beaucoup mieux . Selon la taille de la masse, Model.create() va même planter! Essayé avec un million de documents, pas de chance. En utilisant Model.collection.insert cela ne prit que quelques secondes.

Model.collection.insert(docs, options, callback)
  • docs est le tableau de documents à insérer;
  • options est un objet de configuration facultatif - voir la documentation
  • callback(err, docs) sera appelé une fois tous les documents enregistrés ou une erreur se produit. En cas de succès, docs est le tableau des documents persistants.

Comme le souligne l'auteur de Mongoose here , cette méthode contournera toutes les procédures de validation et permettra d'accéder directement au pilote Mongo. C'est un compromis que vous devez faire puisque vous manipulez une grande quantité de données, sinon vous ne pourriez pas l'insérer du tout dans votre base de données (rappelez-vous que nous parlons de centaines de milliers de documents ici).

Un exemple simple

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);
    }
}

Mise à jour 2019-06-22 : Bien que insert() puisse encore être utilisé, il est déconseillé en faveur de insertMany() . Les paramètres sont exactement les mêmes, vous pouvez donc l'utiliser comme remplacement immédiat et tout devrait bien fonctionner (la valeur de retour est un peu différente, mais vous ne l'utilisez probablement pas de toute façon).

Référence

150
Lucio Paiva

Mongoose 4.4.0 prend désormais en charge l'insertion en bloc

Mongoose 4.4.0 introduit l'insertion --true-- en bloc avec la méthode modèle .insertMany(). C'est beaucoup plus rapide que de boucler sur .create() ou de lui donner un tableau.

Usage:

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

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

Ou

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

Vous pouvez le suivre sur:

108
Derek

En effet, vous pouvez utiliser la méthode "create" de Mongoose, elle peut contenir un tableau de documents, voir cet exemple:

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

La fonction de rappel contient les documents insérés. Vous ne savez pas toujours combien d'éléments doivent être insérés (longueur d'argument fixe comme ci-dessus), vous pouvez donc les parcourir en boucle:

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

Mise à jour: une meilleure solution

Une meilleure solution consisterait à utiliser Candy.collection.insert() au lieu de Candy.create() - utilisé dans l'exemple ci-dessus - car il est plus rapide (create() appelle Model.save() sur chaque élément, donc il est plus lent).

Voir la documentation Mongo pour plus d'informations: http://docs.mongodb.org/manual/reference/method/db.collection.insert/

(merci à arcseldon pour l'avoir signalé)

23
benske

Vous pouvez effectuer une insertion en bloc en utilisant mongoDB Shell en insérant les valeurs dans un tableau.

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

Vous pouvez effectuer une insertion en bloc en utilisant mangouste, en tant que meilleure réponse. Mais l'exemple ne peut pas fonctionner, il devrait être:

/* 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);
    }
}

N'utilisez pas d'instance de schéma pour l'insertion en bloc, vous devez utiliser un objet de carte brut.

4
user2582680

Voici les deux manières de sauvegarder des données avec insertMany et de sauvegarder

1) Mongoose sauvegarde un tableau de documents avec insertMany en bloc

/* 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) Mongoose sauve un tableau de documents avec .save()

Ces documents permettront d'économiser en parallèle.

/* 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});
        })
    })
})
3
Arpit

Il semble que l’utilisation de la mangouste soit limitée à plus de 1000 documents.

Potato.collection.insert(potatoBag, onInsert);

Vous pouvez utiliser:

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)
      });
});

Mais c'est presque deux fois plus rapide quand on teste avec 10 000 documents:

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);
    });
}
3
ddennis

J'ai utilisé async-forEach ( lien pour la documentation du paquet aspm-forEach npm ) pour obtenir le même résultat.

Mon extrait de code est comme ci-dessous. Je reçois les documents dans le corps.

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");
        }
    });       

  });    
 }
2

Partage du code de travail et pertinent de notre projet:

//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);
    });
1
student