I have a collection with a unique field on it. Let's say I create the value of this unique field in the pre save method like this:
schema.pre('save', function (next) {
var _self = this;
try {
if (config.devMode) {
log.debug('[' + si.name + ':write] - Executing presave on: ' + _self._id);
}
if(!_self.transaction_id){
_self.transaction_id = powm(30).toLowerCase();
}
next();
} catch (e) {
log.error('[' + si.name + ':write] - threw an error (SAVE): ', e.stack, _self);
next(e);
}
});
Powm creates an aleatory string like 'dfjkfj3434jkl23k4j2k3j4asdf', which needs to be unique. Although the string is long enough to not be duplicated, I want to be sure that if it is I can retry the saving with a new one till there is a really unique value on it.
I know MongoDB throws an error that bubbles up when saving the document like this:
documentname.save(function(err, doc){
// If mongodb unique error then reset with a new id and resave
});
But this forces me to look for all places in the code where this happens. So I was wondering if I can catch this error in the post mongoose middleware. The problem is that no error object seems to be passed to post save method. So, any idea on this? Thanks!
I'm answering with what I found out right now by stumbling on a similar issue.
I'll be focusing in the "catch error in post save" part as I'm not sure, by now if modifying and re-saving the document in this way might or might not cause some trouble. So I'm not sure this will work fine for your specific needs, but you can give it a try.
My scenario is similar to yours, but slightly different:
I do not generate it randomly at each insertion, but I pre-generated a collection of 1M random codes stored in documents like this:
{
value: "khsda",
status: "FREE"
}
Each time I want to insert a new document with an associated code I do the fallowing:
.pre('validate',...)
I select a "FREE"
code and set its status to "PENDING"
.code
to the value
of the picked code."TAKEN"
otherwise, I want to freed the code, setting its status back to "FREE"
..post('save',...)
middleware that changes the code status
to "TAKEN"
.post('validation',...)
middleware. But here's the quirk: the signature of the function I pass to the middleware must be function(error, doc, next)
. This middleware will be called only if an error occurs in the validation process and lets me put back the status
of the code to "FREE"
.So, basically, you could hook a middleware like this:
schema.post('save', function(err, doc, next) {
// Handle the error...
});
I'm not sure if attempting to change and re-save the document at this point will cause any issue, but by logic, the save operation should already have been aborted and here you can control the bubbling of the error through the next()
. If you attempt a new save and then call next()
without any error as argument, It might work as you need.
Let me know if this works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With