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.