MongoDB的JSON Schema验证是兜底防线而非锦上添花,因应用层校验可能被绕过,只有服务端强制验证才能确保非法写入被mongod拒绝;它仅对insert/update类操作生效,需通过createCollection或collMod启用,且validationAction必须设为"error"。

为什么直接在应用层校验不够用
MongoDB 的 JSON Schema 验证不是锦上添花,而是兜底防线。应用代码可能绕过、SDK 版本不一致、直连 shell 或 Compass 修改数据时,校验就彻底失效。只有服务端强制验证才能保证 mongod 拒绝非法写入,哪怕只是一条 db.users.insertOne({ phone: "abc" })。
Schema 验证只对 insert 和 update 生效(含 replaceOne、findOneAndUpdate),find 类操作完全不触发。
如何为集合启用 JSON Schema 验证器
验证器必须通过 collMod 命令或创建集合时指定,不能靠修改 collection 对象属性生效。
推荐在创建集合时一次性配好,避免后期迁移风险:
db.createCollection("users", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "email"],
properties: {
name: { bsonType: "string", maxLength: 50 },
email: {
bsonType: "string",
pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
},
phone: {
bsonType: "string",
pattern: "^1[3-9]\d{9}$", // 仅中国大陆手机号
description: "敏感字段:必须符合11位手机号格式"
}
}
}
},
validationLevel: "strict", // "off" / "moderate" / "strict"
validationAction: "error" // "warn" / "error"
})
-
validationLevel: "strict"表示所有写操作都校验;"moderate"只校验 insert 和 replace(不校验 update 中的 $set) -
validationAction: "error"是关键——设为"warn"时,非法数据仍会写入,只打日志 - 已有集合需用
db.runCommand({ collMod: "users", validator: { ... } }),但注意:命令执行期间集合可读不可写
敏感字段校验的常见陷阱 JSON Schema 对“敏感字段”的约束容易误以为能覆盖全部场景,实际有硬性限制:
比如想禁止空字符串、null、或未传字段,光靠 required 不够:
-
required: ["phone"]只检查字段是否存在,不阻止{ phone: "" }或{ phone: null } - 要真正拦截空值,得加显式类型和最小长度:
{ bsonType: "string", minLength: 11 } -
pattern无法校验数字类型字段(如bsonType: "int"),手机号若存成数字,正则直接失效——必须统一存为字符串 - 嵌套对象里的敏感字段(如
profile.idCard)需完整路径写进properties,不能只写idCard
验证失败时的真实报错表现
不是所有驱动都友好透出 Schema 错误细节。Node.js 的 mongodb 驱动抛出 MongoWriteConcernError,但错误信息藏在 error.errInfo.details.schemaRulesNotSatisfied 里,而不是 message 字段。
最简排查方式是用 mongo shell 直接试:
db.users.insertOne({ name: "Alice", email: "a@b.c", phone: "123" })
// → WriteResult({ "nInserted" : 0, "writeError" : { "code" : 121, "errmsg" : "Document failed validation" } })
- 错误码
121固定表示 Schema 验证失败 - 要看到具体哪条 rule 不满足,得开启
validationLevel: "strict"+validationAction: "error",并查日志(db.setLogLevel(1, "storage")不适用,得看 mongod 启动日志) - Compass 界面不会显示失败原因,只会提示“Write failed”,必须切到 shell 或驱动日志里找
MongoDB 的 JSON Schema 验证本质是 BSON 层过滤器,它不支持自定义函数、不访问其他文档、也不做跨字段逻辑(比如“password 和 confirmPassword 必须一致”)。真有这类需求,得回到应用层,或者用 Change Streams + 外部校验服务兜底。











