首页 文章

Mongoose findOneAndUpdate和runValidators无法正常工作

提问于
浏览
23

我在尝试使用'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操作上运行 . 例如,无论number的值如何,以下更新都将成功 .

我用$ set替换了$ setOnInsert,但结果相同 .

4 回答

  • 4

    当您尝试显式$取消设置密钥时,所需的验证程序仅会失败 .

    这对我来说毫无意义,但这是文档所说的 .

  • 2

    在猫鼬中分两步做同样的事情 .

    • 使用 findOne() 方法查找结果 .

    • 使用 Model.save() 添加字段并保存文档 .

    这将更新您的文档 .

  • 5

    我在mongoose中执行更新操作之前创建了一个插件来验证所需的模型属性 .

    Plugin code here

    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 链 .

    Plugin in use here

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

    使用这个插件:mongoose-unique-validator

    使用像 findOneAndUpdate 这样的方法时,您需要传递此配置对象:

    {runValidators:true,context:'query'}

    即 .

    User.findOneAndUpdate(
      { email: 'old-email@example.com' },
      { email: 'new-email@example.com' },
      { runValidators: true, context: 'query' },
      function(err) {
        // ...
    }
    

相关问题