I have a collection that holds documents that contains three fields: first_name, last_name, and age. I\'m trying to figure out what query in Mongoose I can use to do a bulk
(mongoose@4.9.1, mongodb@3.4.2)
After struggling with Mongoose API poor documentation, I solved the bulk upsert tweaking updateOne:{} operation in the bulkWrite() method.
A couple of undocumented things to consider:
// suppose:
var GasStation = mongoose.model('gasstation', gasStationsSchema);
var bulkOps = [ ];
// for ( ... each gasStation to upsert ...) {
let gasStation = { country:'a', localId:'b', xyz:'c' };
// [populate gasStation as needed]
// Each document should look like this: (note the 'upsert': true)
let upsertDoc = {
'updateOne': {
'filter': { 'country': gasStation.country, 'localId': gasStation.localId },
'update': gasStation,
'upsert': true
}};
bulkOps.push(upsertDoc);
// end for loop
// now bulkWrite (note the use of 'Model.collection')
GasStation.collection.bulkWrite(bulkOps)
.then( bulkWriteOpResult => {
console.log('BULK update OK');
console.log(JSON.stringify(bulkWriteOpResult, null, 2));
})
.catch( err => {
console.log('BULK update error');
console.log(JSON.stringify(err, null, 2));
});
The two key things here are incomplete API documentation issues (at the time of writing, at least):
'upsert': true in each document. This is not documented in Mongoose API (), which often refers to node-mongodb-native driver. Looking at updateOne in this driver, you could think to add 'options':{'upsert': true}, but, no... that won't do. I also tried to add both cases to the bulkWrite(,[options],) argument, with no effect either.GasStation.collection.bulkWrite(). Although Mongoose bulkWrite() method claims it should be called Model.bulkWrite() (in this case, GasStation.bulkWrite()), that will trigger MongoError: Unknown modifier: $__. So, Model.collection.bulkWrite() must be used.Additionally, note:
$set mongo operator in the updateOne.update field, since mongoose handles it in case of upsert (see bulkWrite() comments in example).gasStationsSchema.index({ country: 1, localId: 1 }, { unique: true });
Hope it helps.
==> EDIT: (Mongoose 5?)
As noticed by @JustinSmith, the $set operator added by Mongoose doesn't seem to be working anymore. Maybe it's because of Mongoose 5?
In any case, using $set explicitly should do:
'update': { '$set': gasStation },