我的架构看起来像这样:
var minderSchema = mongoose.Schema({
phones: {type: [{
details: {
type: {
country_code: { type: String, required: true },
region_code: { type: String, required: true },
number: { type: Number, required: true }
},
required: true
},
}], required: true},
})
那是......一个监视器由一系列电话组成(这是必需的)。每部手机必须有国家代码,地区代码和号码。但验证似乎不起作用。即我可以创建:
var minder = new Minder({
"phones": [{
details: {
number: "3343434"
}
}]
});
哪些不适用,因为它缺少国家/地区代码和区域代码。事实上,我可以创建一个这样的文档:
var minder = new Minder({
"phones": [{
details: {
"sdf":"sdf"
}
}]
});
它验证了。
我错过了什么概念?
答案 0 :(得分:8)
这里的问题主要在于你如何构建你的"细节"进入这里。因此,尽管您认为自己可能已经做过,但实际上这里的条目类型是一个普通的子文档,或者通常被称为" hash / map或dict"取决于您最熟悉的术语。
严格来说,这些并不是"打字"无论如何,所以没有真正控制"键"你在那里放置。所以你可能想要的是实际上可以用严格类型的方式构建的东西,例如:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
var phonesSchema = new Schema({
country_code: { type: String, required: true },
region_code: { type: String, required: true },
number: { type: String, required: true }
});
var minderSchema = new Schema({
phones:[phonesSchema]
});
var Minder = mongoose.model( 'Minder', minderSchema );
var minder = new Minder({
"phones": [{ "number": "12345", "bill": "45678" }]
});
console.log( JSON.stringify( minder, undefined, 2 ) );
minder.save();
这不仅区分了模式定义(方便和干净),而且现在你有一个明确定义的"子类型"实际上,可以对条目执行验证。如果需要,你可以扩展它,但我通常认为这是更清洁的形式。
这里最后一个重点是实现"验证"实际发生了。因此,从您的示例中您只是创建实例,但这不是验证发生的地方。实际发生的唯一地方是当对象实例被保存时#34;并坚持存储。这允许你构建"对象,但不是严格的验证者"传统"类中的对象"感。
所以运行上面的代码片段,你得到这个输出:
{ _id: 537d7c71d4d04b65174d0c00,
phones: [ { number: '12345', _id: 537d7c71d4d04b65174d0c01 } ] }
events.js:72
throw er; // Unhandled 'error' event
^
No listeners detected, throwing. Consider adding an error listener to your connection.
ValidationError: Path `region_code` is required., Path `country_code` is required.
at model.Document.invalidate (/home/neillunn/node_modules/mongoose/lib/document.js:1009:32)
at EmbeddedDocument.invalidate (/home/neillunn/node_modules/mongoose/lib/types/embedded.js:178:19)
at /home/neillunn/node_modules/mongoose/lib/document.js:958:16
at validate (/home/neillunn/node_modules/mongoose/lib/schematype.js:610:7)
at /home/neillunn/node_modules/mongoose/lib/schematype.js:627:9
at Array.forEach (native)
at SchemaString.SchemaType.doValidate (/home/neillunn/node_modules/mongoose/lib/schematype.js:614:19)
at /home/neillunn/node_modules/mongoose/lib/document.js:956:9
at process._tickCallback (node.js:419:13)
at Function.Module.runMain (module.js:499:11)
注意到" log"输出保持"有效"输入但丢弃了未定义的字段,然后"验证"实际上只有当对象实际尝试"保存"时才会出现所需字段。
因此,请考虑您的结构以及实际验证的实际情况。尝试添加未定义的字段不会出错,它只会丢弃。省略"要求"字段,仅在对象持久化时检查,这允许您有时间构建它。这些不是必需的"类构造函数"类型参数,但用于不同的目的。
如果您真的想要嵌套,请删除"类型"声明如下:
var phonesSchema = new Schema({
details: {
country_code: { type: String, required: true },
region_code: { type: String, required: true },
number: { type: String, required: true }
}
});
验证将对您有用:
{
"_id": "537d9e6d5b433f8745547f52",
"phones": [
{
"_id": "537d9e6d5b433f8745547f53",
"details": {
"number": "12345"
}
}
]
}
events.js:72
throw er; // Unhandled 'error' event
^
No listeners detected, throwing. Consider adding an error listener to your connection.
ValidationError: Path `details.region_code` is required., Path `details.country_code` is required.
答案 1 :(得分:0)
在我的嵌套文档中,我使用了此模块mongoose-unique-validator,但是您也可以使用SchemaName.path("key.nestedKey").validate(argument => {}))
,所以问题是在update
上,猫鼬只对查询进行了解析并在没有验证的情况下运行,以验证您可以作为第三个参数{ runValidators: true }