2012-06-05 3 views
2

У меня есть модель под названием 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'); 

Он вызывает функцию проверки под названием UniqueName, когда он экономит:

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; 
} 

Позже в коде я положил некоторые данные в модели и сохранить его:

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(); 

Когда я проверить это с именем, которое не является уникальным, я получаю 201 ответ и следующий вывод из моего терминала:

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

Я делаю что-то неправильно или это действительно состояние гонки в Мангустасе?

ответ

0

Когда ваш валидатор является асинхронным (как здесь), он должен принять второй параметр, который является обратным вызовом, который вы должны вызывать с истинным или ложным, в зависимости от того, прошла ли эта проверка. Таким образом:

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); 
    } 
} 

Однако это не очень эффективно; вы должны:

Отфильтруйте find вместо того, чтобы получать все документы и вручную искать их. например

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

ИЛИ еще лучше:

Создать уникальный индекс на name и пусть Монго обеспечить уникальность для вас. например

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

Спасибо! Вы правы, я не понимал, что существует уникальный индекс. – amandawulf

+0

Вы должны подчеркнуть, как уникальный индекс действительно является единственным способом решения этой проблемы. Выполнение поиска в подобном валидаторе приводит к состоянию гонки. После того, как ваш поиск в валидаторе вернется к вам, другой документ может быть вставлен в коллекцию с тем же значением для 'name'. Ваш документ все равно пройдет проверку и продолжит запись, в результате чего будут созданы два документа с одинаковым значением для 'name'. Уникальный индекс MongoDB гарантирует, что этого не произойдет (пока вы не отключите проверку индекса при сохранении). – binki

Смежные вопросы