【问题标题】:How do you validate that a property of a nested document is present when that nested document exists?当嵌套文档存在时,如何验证嵌套文档的属性是否存在?
【发布时间】:2015-11-12 05:15:28
【问题描述】:

user.schema.js

var Schema = require('mongoose').Schema;
var uniqueValidator = require('mongoose-unique-validator');
var _ = require('lodash');

var userSchema = new Schema({
  local: {
    username: String, // should exist when local exists
    role: String,
    hashedPassword: { type: String, select: false }
  },

  facebook: {
    id: String,
    token: { type: String, select: false }
  },

  twitter: {
    id: String,
    token: { type: String, select: false }
  },

  google: {
    id: String,
    token: { type: String, select: false }
  }
});

userSchema.path('local').validate(function(local) {
  var empty = _.isEmpty(local);
  if (empty) {
    return true;
  }
  else if (!empty && local.username) {
    return true;
  }
  else if (!empty && !local.username) {
    return false;
  }
}, 'Local auth requires a username.');

module.exports = userSchema;

local 不为空时,我正在尝试验证username 是否存在。 IE。使用本地身份验证时,username 应该存在。

// should validate
user = {
  local: {
    username: 'foo';
    hashedPassword: 'sfsdfs'
  }
};

// shouldn't validate
user = {
  local: {
    hashedPassword: 'sdfsdfs'
  }
};

// should validate (because local isn't being used)
user = {
  local: {},
  facebook {
    ...
  }
};

我收到此错误:

/Users/azerner/code/mean-starter/server/api/users/user.schema.js:51
userSchema.path('local').validate(function(local) {
                        ^
TypeError: Cannot read property 'validate' of undefined

您似乎无法获取对象的path。我了解到here Schemas 有一个paths 属性。当我console.log(userSchema.paths)

{ 'local.username':
   { enumValues: [],
     regExp: null,
     path: 'local.username',
     instance: 'String',
     validators: [],
     setters: [],
     getters: [],
     options: { type: [Function: String] },
     _index: null },
  'local.role':
   { enumValues: [],
     regExp: null,
     path: 'local.role',
     instance: 'String',
     validators: [],
     setters: [],
     getters: [],
     options: { type: [Function: String] },
     _index: null },
  'local.hashedPassword':
   { enumValues: [],
     regExp: null,
     path: 'local.hashedPassword',
     instance: 'String',
     validators: [],
     setters: [],
     getters: [],
     options: { type: [Function: String], select: false },
     _index: null,
     selected: false },
  'facebook.id':
   { enumValues: [],
     regExp: null,
     path: 'facebook.id',
     instance: 'String',
     validators: [],
     setters: [],
     getters: [],
     options: { type: [Function: String] },
     _index: null },
  'facebook.token':
   { enumValues: [],
     regExp: null,
     path: 'facebook.token',
     instance: 'String',
     validators: [],
     setters: [],
     getters: [],
     options: { type: [Function: String], select: false },
     _index: null,
     selected: false },
  'twitter.id':
   { enumValues: [],
     regExp: null,
     path: 'twitter.id',
     instance: 'String',
     validators: [],
     setters: [],
     getters: [],
     options: { type: [Function: String] },
     _index: null },
  'twitter.token':
   { enumValues: [],
     regExp: null,
     path: 'twitter.token',
     instance: 'String',
     validators: [],
     setters: [],
     getters: [],
     options: { type: [Function: String], select: false },
     _index: null,
     selected: false },
  'google.id':
   { enumValues: [],
     regExp: null,
     path: 'google.id',
     instance: 'String',
     validators: [],
     setters: [],
     getters: [],
     options: { type: [Function: String] },
     _index: null },
  'google.token':
   { enumValues: [],
     regExp: null,
     path: 'google.token',
     instance: 'String',
     validators: [],
     setters: [],
     getters: [],
     options: { type: [Function: String], select: false },
     _index: null,
     selected: false },
  _id:
   { path: '_id',
     instance: 'ObjectID',
     validators: [],
     setters: [ [Function: resetId] ],
     getters: [],
     options: { type: [Object], auto: true },
     _index: null,
     defaultValue: [Function: defaultId] } }

因此,local.usernamefacebook.token 之类的路径似乎存在,但 localfacebook 之类的“顶级”路径不存在。

如果我尝试验证 local.username 路径,它不会像我想要的那样工作。

userSchema.path('local.username').validate(function(username) {
  return !!username
}, 'Local auth requires a username.');

仅当local.username 存在时才应用验证。我想验证它是否存在。因此,当它不存在时,不会应用验证,因此它被认为是有效的并被保存。

我也尝试了以下方法,但结果与local.username 方法相同(当用户名不存在时验证不会被命中,它会被标记为有效)。

var Schema = require('mongoose').Schema;
var uniqueValidator = require('mongoose-unique-validator');
var _ = require('lodash');

var userSchema = new Schema({
  local: {
    username: {
      type: String,
      validate: [validateUsernameRequired, 'Local auth requires a username.']
    },
    role: String,
    hashedPassword: { type: String, select: false }
  },

  facebook: {
    id: String,
    token: { type: String, select: false }
  },

  twitter: {
    id: String,
    token: { type: String, select: false }
  },

  google: {
    id: String,
    token: { type: String, select: false }
  }
});

function validateUsernameRequired(username) {
  return !!username;
}

module.exports = userSchema;

【问题讨论】:

    标签: javascript mongoose


    【解决方案1】:

    亚当,你为什么不尝试一个预验证钩子,它有条件地将错误传递给下一个函数。我认为这将为您提供所需的灵活性。如果它不起作用,请告诉我。

    例如

    schema.pre('validate', function(next) {
      if(/*your error case */){ next('validation error text') }
      else { next() }
    })
    

    这将导致 mongoose 将 ValidationError 发回给试图保存文档的人。

    【讨论】:

      【解决方案2】:

      看起来您正在尝试创建自定义验证。不确定您是否实现了所需的一切。它看起来像这样:

      // make sure every value is equal to "something"
      function validator (val) {
        return val == 'something';
      }
      new Schema({ name: { type: String, validate: validator }});
      
      // with a custom error message
      
      var custom = [validator, 'Uh oh, {PATH} does not equal "something".']
      new Schema({ name: { type: String, validate: custom }});
      
      // adding many validators at a time
      
      var many = [
          { validator: validator, msg: 'uh oh' }
        , { validator: anotherValidator, msg: 'failed' }
      ]
      new Schema({ name: { type: String, validate: many }});
      
      // or utilizing SchemaType methods directly:
      
      var schema = new Schema({ name: 'string' });
      schema.path('name').validate(validator, 'validation of `{PATH}` failed with 
      value `{VALUE}`');
      

      这里是链接:mongoose custom validation

      【讨论】:

        猜你喜欢
        • 2017-07-25
        • 1970-01-01
        • 2017-05-20
        • 2018-09-19
        • 1970-01-01
        • 2018-03-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多