How can I save multiple documents concurrently in Mongoose/Node.js?

后端 未结 13 1869
南笙
南笙 2020-12-07 10:20

At the moment I use save to add a single document. Suppose I have an array of documents that I wish to store as single objects. Is there a way of adding them all with a si

相关标签:
13条回答
  • 2020-12-07 10:56

    This is an old question, but it came up first for me in google results when searching "mongoose insert array of documents".

    There are two options model.create() [mongoose] and model.collection.insert() [mongodb] which you can use. View a more thorough discussion here of the pros/cons of each option:

    Mongoose (mongodb) batch insert?

    0 讨论(0)
  • 2020-12-07 10:58

    Here is an example of using MongoDB's Model.collection.insert() directly in Mongoose. Please note that if you don't have so many documents, say less than 100 documents, you don't need to use MongoDB's bulk operation (see this).

    MongoDB also supports bulk insert through passing an array of documents to the db.collection.insert() method.

    var mongoose = require('mongoose');
    
    var userSchema = mongoose.Schema({
      email : { type: String, index: { unique: true } },
      name  : String  
    }); 
    
    var User = mongoose.model('User', userSchema);
    
    
    function saveUsers(users) {
      User.collection.insert(users, function callback(error, insertedDocs) {
        // Here I use KrisKowal's Q (https://github.com/kriskowal/q) to return a promise, 
        // so that the caller of this function can act upon its success or failure
        if (!error)
          return Q.resolve(insertedDocs);
        else
          return Q.reject({ error: error });
      });
    }
    
    var users = [{email: 'foo@bar.com', name: 'foo'}, {email: 'baz@bar.com', name: 'baz'}];
    saveUsers(users).then(function() {
      // handle success case here
    })
    .fail(function(error) {
      // handle error case here
    });
    
    0 讨论(0)
  • 2020-12-07 11:04

    Mongoose 4.4 added a method called insertMany

    Shortcut for validating an array of documents and inserting them into MongoDB if they're all valid. This function is faster than .create() because it only sends one operation to the server, rather than one for each document.

    Quoting vkarpov15 from issue #723:

    The tradeoffs are that insertMany() doesn't trigger pre-save hooks, but it should have better performance because it only makes 1 round-trip to the database rather than 1 for each document.

    The method's signature is identical to create:

    Model.insertMany([ ... ], (err, docs) => {
      ...
    })
    

    Or, with promises:

    Model.insertMany([ ... ]).then((docs) => {
      ...
    }).catch((err) => {
      ...
    })
    
    0 讨论(0)
  • 2020-12-07 11:04

    Newer versions of MongoDB support bulk operations:

    var col = db.collection('people');
    var batch = col.initializeUnorderedBulkOp();
    
    batch.insert({name: "John"});
    batch.insert({name: "Jane"});
    batch.insert({name: "Jason"});
    batch.insert({name: "Joanne"});
    
    batch.execute(function(err, result) {
        if (err) console.error(err);
        console.log('Inserted ' + result.nInserted + ' row(s).');
    }
    
    0 讨论(0)
  • 2020-12-07 11:05

    I know this is an old question, but it worries me that there are no properly correct answers here. Most answers just talk about iterating through all the documents and saving each of them individually, which is a BAD idea if you have more than a few documents, and the process gets repeated for even one in many requests.

    MongoDB specifically has a batchInsert() call for inserting multiple documents, and this should be used from the native mongodb driver. Mongoose is built on this driver, and it doesn't have support for batch inserts. It probably makes sense as it is supposed to be a Object document modelling tool for MongoDB.

    Solution: Mongoose comes with the native MongoDB driver. You can use that driver by requiring it require('mongoose/node_modules/mongodb') (not too sure about this, but you can always install the mongodb npm again if it doesn't work, but I think it should) and then do a proper batchInsert

    0 讨论(0)
  • 2020-12-07 11:11

    Mongoose does now support passing multiple document structures to Model.create. To quote their API example, it supports being passed either an array or a varargs list of objects with a callback at the end:

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

    Or

    var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
    Candy.create(array, function (err, jellybean, snickers) {
        if (err) // ...
    });
    

    Edit: As many have noted, this does not perform a true bulk insert - it simply hides the complexity of calling save multiple times yourself. There are answers and comments below explaining how to use the actual Mongo driver to achieve a bulk insert in the interest of performance.

    0 讨论(0)
提交回复
热议问题