Created
September 28, 2017 10:20
-
-
Save d1manson/a36c18ae5c77a2a141b902e7c614bc62 to your computer and use it in GitHub Desktop.
Unlike findOneAndUpdate, this returns both the old and the new docs, the operation is performed atomically
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Unlike findOneAndUpdate, this returns both the old and the new docs, | |
the operation is performed atomically. | |
Note that although it can apply defaults properly, it does not apply | |
pre-update hooks, with the exception of timestamps (see note in code). | |
Example: | |
Dogs.upsert({owner: 'wallace', name: 'grommit'}, {breakfast: 'eggs'}) | |
.then(res => console.dir({'old': res.oldDoc, 'new': res.newDoc})); | |
*/ | |
module.exports = function UpsertPlugin(schema){ | |
schema.statics.upsert = function(query, update){ | |
update = update.$set || update; | |
let preemptiveData = (new this(query)).toJSON(); | |
Object.keys(update).forEach(k => delete preemptiveData[k]); // need fields to be unique for $set/$setOnInsert | |
return this.findOneAndUpdate(query, { | |
$set: update, | |
$setOnInsert: preemptiveData | |
}, { | |
upsert: true, | |
new: false, | |
setDefaultsOnInsert: false // we have explicitly dealt with this above | |
}).then(oldDoc => { | |
// Deal with timestamps on the collection - this is rather hacky and | |
// actually means the values stored will be ever so slightly earlier | |
// than the values returned to the caller of this function. | |
let timestamps = schema.options.timestamps; | |
if(timestamps && timestamps.updatedAt){ | |
update[timestamps.updatedAt] = Date.now(); | |
} | |
if(!oldDoc && timestamps && timestamps.createdAt){ | |
update[timestamps.createdAt] = Date.now(); | |
} | |
let newDoc = new this(Object.assign(oldDoc ? oldDoc.toJSON() : preemptiveData, update)); | |
newDoc.isNew = false; // we have upserted it!!! | |
return { | |
oldDoc, | |
newDoc: newDoc | |
}; | |
}); | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment