这里的问题主要在于您如何构建“details”入口。所以尽管您认为自己已经完成了,实际上这里存在的条目类型是一个简单的子文档或者通常被称为“哈希/映射或字典”的东西,具体由您熟悉哪个术语而定。
它们在任何情况下都不是严格意义上的“类型化”,因此对于您放置在其中的“键”没有真正的控制。因此,您可能需要的是一些可以以严格类型化方式结构化的内容,例如:
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();
这不仅可以将模式定义(更方便和清晰),而且现在您拥有一个明确定义的“子类型”,可以在其中执行条目的验证。如有需要,您可以进行扩展,但我通常认为这是更干净的形式。
这里最后一个重要的观点是要意识到“验证”实际上发生在哪里。因此,从您的示例中,您只是创建实例,但这并不是验证发生的地方。这实际上只有在对象实例被“保存”并持久化到存储时才会发生。这使您能够“构建”对象,但不是传统“类”意义上的严格的“验证器”。
运行上面的片段,您会得到此输出:
{ _id: 537d7c71d4d04b65174d0c00,
phones: [ { number: '12345', _id: 537d7c71d4d04b65174d0c01 } ] }
events.js:72
throw er;
^
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)
注意到这里的“日志”输出保留了“有效”的条目,但丢弃了未定义的字段,然后“验证”只在对象实际尝试“保存”时针对所需字段进行。
因此,请考虑您的结构以及实际发生的验证情况。尝试添加未定义的字段不会出错,它只会被丢弃。省略“必需”的字段仅在对象持久化时检查,这使您有时间构建它。这些不是必需的“类构造函数”类型参数,而是为其他目的而设计的。
如果您真的想要嵌套,则可将“type”声明删除,如下:
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;
^
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.