Подтвердить что ты не робот

Mongoose findOneAndUpdate и runValidators не работают

У меня возникают проблемы с попыткой работать с параметром "runValidators". Моя пользовательская схема имеет поле электронной почты, для которого требуется значение true, но каждый раз, когда новый пользователь добавляется в базу данных (с использованием опции "upsert" ), а поле электронной почты пуст, оно не жалуется:

 var userSchema = new mongoose.Schema({
   facebookId: {type: Number, required: true},
   activated: {type: Boolean, required: true, default: false},
   email: {type: String, required: true}
});

findOneAndUpdate код:

model.user.user.findOneAndUpdate(
      {facebookId: request.params.facebookId},
      {
          $setOnInsert: {
              facebookId: request.params.facebookId,
              email: request.payload.email,
          }
      },
      {upsert: true, 
       new: true, 
       runValidators: true, 
       setDefaultsOnInsert: true
      }, function (err, user) {
          if (err) {
              console.log(err);
              return reply(boom.badRequest(authError));
          }
          return reply(user);
      });

Я понятия не имею, что я делаю неправильно, я просто следовал за документами: http://mongoosejs.com/docs/validation.html

В документах говорится следующее:

Обратите внимание, что в mongoose 4.x обновления проверяют только на операции $set и $unset. Например, нижеприведенное обновление будет выполнено, независимо от значения числа.

Я заменил $setOnInsert на $set, но имел тот же результат.

4b9b3361

Ответ 1

требуемые валидаторы только терпят неудачу, когда вы пытаетесь явно отключить ключ.

Это не имеет никакого смысла для меня, но это то, что говорят документы.

Ответ 2

В мангусте делать то же самое в два этапа.

  • Найти результат с помощью метода findOne().
  • Добавить поля и сохранить документ с помощью Model.save().

Это обновит ваш документ.

Ответ 3

Я создал плагин для проверки необходимых свойств модели перед выполнением операций обновления в мангусте.

Код плагина здесь

var mongoose = require('mongoose');
var _ = require('lodash');
var s = require('underscore.string');

function validateExtra(schema, options){
    schema.methods.validateRequired = function(){
        var deferred = Promise.defer();
        var self = this;
        try {
            _.forEach(this.schema.paths, function (val, key) {
                if (val.isRequired && _.isUndefined(self[key])) {
                    throw new Error(s.humanize(key) + ' is not set and is required');
                }
            });
            deferred.resolve();
        } catch (err){
            deferred.reject(err);
        }
        return deferred.promise;
    }
}

module.exports = validateExtra;

Должен быть вызван явно как метод из модели, поэтому я рекомендую привязать цепочку .then до вызова обновления.

Плагин, используемый здесь

fuelOrderModel(postVars.fuelOrder).validateRequired()
    .then(function(){
        return fuelOrderModel.findOneAndUpdate({_id: postVars.fuelOrder.fuelOrderId}, 
           postVars.fuelOrder, {runValidators: true, upsert: true, 
           setDefaultsOnInsert: true, new: true})
                .then(function(doc) {
                    res.json({fuelOrderId: postVars.fuelOrder.fuelOrderId});
                });
    }, function(err){
            global.saveError(err, 'server', req.user);
            res.status(500).json(err);
    });

Ответ 4

используйте этот плагин: mongoose-unique-validator

При использовании таких методов, как findOneAndUpdate, вам необходимо передать этот объект конфигурации:

{runValidators: true, context: 'query'}

т.

User.findOneAndUpdate(
  { email: '[email protected]' },
  { email: '[email protected]' },
  { runValidators: true, context: 'query' },
  function(err) {
    // ...
}