简体   繁体   中英

Mongoose Validation Race Condition?

I have a model called Application:

var ApplicationSchema = new mongoose.Schema({
name       : {type: String, validate: [uniqueName, 'Unique Name']},
dateCreated: Date,
containers : [ContainerSchema]
});
mongoose.model('Application', ApplicationSchema);
var Application = database.model('Application');

It calls a validation function called uniqueName when it saves:

function uniqueName(name)
{
console.log('In Unique Name function');
Application.find({}, function(error, documents) {
    for(var i = 0; i < documents.length; i++) {
        if(documents[i].name == name) {
            console.log('About to return false');
            return false;
        }
    }
});
return true;
}

Later on in the code I put some data in the model and save it:

newApplication.name = request.body.name;
newApplication.save(function(error) {
    console.log('Callback for save');
    if(error) {
        console.log('error if statement');
        response.statusCode = 409;
        response.end();
    }
    console.log('Done with callback');
});
response.statusCode = 201;
response.end();

When I test this with a name that is not unique, I get a 201 response and the following output from my terminal:

In Unique Name function
Callback for save
Done with callback
About to return false

Am I doing something wrong, or is this really a race condition in Mongoose?

When your validator is asynchronous (as it is here) it needs to accept a second parameter which is a callback that you must call with true or false, depending on whether that validation passed. So:

function uniqueName(name, callback)
{
    Application.find({}, function(error, documents) {
        for(var i = 0; i < documents.length; i++) {
            if(documents[i].name == name) {
                return callback(false);
            }
        }
        return callback(true);
    }
}

However, this is not very efficient; you should either:

Filter your find instead of getting all docs and manually searching them. eg

Application.find({name: name} ...

OR even better:

Create a unique index on name and let mongo ensure uniqueness for you. eg

var ApplicationSchema = new mongoose.Schema({
    name: {type: String, unique: true}, 
    ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM