MongoDB的模式验证功能允许我们在集合级别定义数据规范,当插入或更新文档不符合规范时,数据库可以直接拒绝写入。其底层依赖JSON Schema标准,但在具体关键字上做了面向BSON的扩展。理解这些语法细节,是避免脏数据进入系统的关键。

校验器的挂载与基本结构
在MongoDB中,模式验证通过collMod命令或创建集合时的validator选项来定义。验证器内部使用$jsonSchema关键字来承载JSON Schema文档。这个Schema本身是一个普通的BSON对象,描述了文档允许具有的字段、类型以及约束条件。
需要特别注意,MongoDB使用的是bsonType而非标准JSON Schema里的type来声明BSON类型。如果你写了type: "string",MongoDB并不会按预期工作,必须写成bsonType: "string"。下面是一个最基础的验证器创建示例,要求文档必须包含一个字符串类型的name字段。
db.createCollection("users", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name"],
properties: {
name: {
bsonType: "string",
description: "姓名必须为字符串且必填"
}
}
}
},
validationLevel: "strict",
validationAction: "error"
});
上述代码中的validationLevel控制校验范围,strict表示对插入和更新的文档都校验;validationAction设为error时校验失败会直接抛错,若设为warn则只记录日志不阻断。生产环境通常建议使用error以强制约束数据质量。
字段约束与常用关键字详解
在properties中,我们可以对每个字段单独设置规则。除了bsonType,还经常用到minimum、maximum做数值边界控制,用pattern做正则匹配,用enum限制枚举值。例如年龄字段要求为大于0且小于120的整数,状态只能是 active 或 disabled。
下面的示例展示了复合约束写法。注意pattern中使用的是标准JavaScript正则语法,不需要额外转义斜杠。当文档的age或status不满足时,写入就会被拒绝。
db.runCommand({
collMod: "users",
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "age", "status"],
properties: {
name: {
bsonType: "string",
minLength: 1,
maxLength: 50
},
age: {
bsonType: "int",
minimum: 1,
maximum: 120
},
status: {
bsonType: "string",
enum: ["active", "disabled"]
},
email: {
bsonType: "string",
pattern: "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
}
}
}
}
});
对于嵌套文档,可以将properties继续嵌套展开。比如address字段本身是个对象,里面包含city和zip,我们可以在内层再用bsonType和required描述。数组元素则通过items关键字约束,例如要求tags数组的每个元素都是字符串。
db.runCommand({
collMod: "users",
validator: {
$jsonSchema: {
bsonType: "object",
properties: {
address: {
bsonType: "object",
required: ["city"],
properties: {
city: { bsonType: "string" },
zip: { bsonType: "string" }
}
},
tags: {
bsonType: "array",
items: { bsonType: "string" }
}
}
}
}
});
这种分层描述方式让我们能精确控制复杂结构。但要注意,如果父级字段没有写required,那么该字段可以缺失,其内部的required也就不再生效。因此在设计Schema时,必填性需要从外层向内层逐层声明。
校验失败处理与版本兼容
当应用写入不符合Schema的文档时,MongoDB会返回错误码121,并附带具体的失败原因,比如哪个字段类型不对或缺少必填项。在应用层应当捕获该错误并转换为友好的提示,而不是简单抛出数据库异常。
不同MongoDB版本对JSON Schema的支持程度略有差异。3.6引入了基础支持,4.0后增强了对uniqueItems、additionalProperties等关键字的处理。如果集群中存在旧节点,某些关键字可能被忽略。因此上线前应在目标版本实例上做充分测试,避免语法在本地可用却在线上失效。
try {
db.users.insertOne({ name: 123 });
} catch (e) {
if (e.code === 121) {
print("模式验证失败:" + e.errmsg);
} else {
throw e;
}
}
另外,已存在的集合可以通过collMod随时调整验证器,但修改不会影响已有文档,除非使用validationLevel: "moderate"让更新操作也校验旧文档。若需全量清洗数据,可以写脚本遍历并修复不合规记录,再开启严格校验。合理运用这些机制,才能让MongoDB既保持灵活又具备可靠的数据约束能力。
MongoDBJSON_Schema模式验证修改时间:2026-08-15 23:06:12