当嵌套文档存在时,如何验证嵌套文档的属性是否存在? [英] How do you validate that a property of a nested document is present when that nested document exists?
问题描述
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屋!