当嵌套文档存在时,如何验证嵌套文档的属性是否存在? [英] How do you validate that a property of a nested document is present when that nested document exists?

查看:63
本文介绍了当嵌套文档存在时,如何验证嵌套文档的属性是否存在?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 不为空时出现。 IE浏览器。使用本地身份验证时,用户名应该存在。

I'm trying to validate that username is present when local isn't empty. Ie. when using local authentication, username should be present.

// 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

看来你无法获得对象的路径。我学到了这里架构有一个路径属性。当我 console.log(userSchema.paths)

It seems that you can't get the path of objects. I learned here that Schemas have a paths property. When I 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.username facebook.token 存在,但不是顶级路径,如 local facebook

So it seems that paths like local.username and facebook.token exist, but not "top level" paths like local and facebook.

如果我尝试val id local.username 路径,它不能像我想要的那样工作。

If I try to validate the local.username path, it doesn't work like I want it to.

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

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

The validation is only applied when local.username exists. I want to validate that it exists. So when it doesn't exist, the validation isn't applied, and thus it's considered valid and gets saved.

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

I also tried the following approach, but the outcome is the same as the local.username approach (validation doesn't get hit when the username isn't present, and it gets labeled as valid).

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;


推荐答案

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

Adam, why don't you try a pre-validate hook that conditionally passes an error to the next function. I think this'll give you the flexibility you're looking for. Let me know if it doesn't work.

例如

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

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

This will cause mongoose to send a ValidationError back to whoever tried to save the document.

这篇关于当嵌套文档存在时,如何验证嵌套文档的属性是否存在?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆