mongodb默认不校验schema漂移,因validationlevel默认为"off";需显式设为"strict"并配合validator才能在写入时硬性拦截非法结构,否则即使定义完整规则也无效。

MongoDB 本身不阻止 Schema 漂移,但你可以用 validator + validationLevel: "strict" + validationAction: "error" 组合,在写入时硬性拦截非法结构,从源头掐断漂移引发的程序错误。
为什么默认不生效?validator 必须配 validationLevel 才起作用
只在 createCollection 或 collMod 中写 validator 是不够的。MongoDB 会忽略它,除非同时指定 validationLevel。常见错误现象是:schema 写得再全,db.users.insert({ name: 123 }) 依然成功——因为没设 validationLevel。
-
validationLevel: "off":完全不校验(默认值,极易被忽略) -
validationLevel: "strict":所有插入/更新都校验(推荐,防漂移最直接) -
validationLevel: "moderate":只校验已存在字段,新字段放行(适合灰度过渡,但防不住新增非法字段)
required 不等于“非空”,null 值仍能绕过校验
比如你写了 "required": ["email"],但客户端传 { email: null },MongoDB 会接受——因为字段存在,只是值为 null。这会导致下游程序调用 .split("@") 报错。
- 要真正排除
null,得在字段级加"not": { "type": "null" } - 或者用
"enum"显式列出允许值,避开null和空字符串 - 对时间字段,
"type": "string"+"format": "date-time"比只写"type": "string"更可靠,否则"2026-05-13"和"garbage"都算合法
嵌套字段和数组必须逐层定义,点号路径无效
不能写 "user.profile.phone": { "bsonType": "string" } —— JSON Schema 不识别点号。MongoDB 会静默忽略该规则,导致 profile 缺失或 phone 类型错误都不报错。
- 正确写法是用
properties嵌套:"profile": { "bsonType": "object", "properties": { "phone": { "bsonType": "string" } } } - 数组元素校验必须用
"items":"tags": { "bsonType": "array", "items": { "bsonType": "string" } } - ObjectId 字段需正则校验:
"_id": { "pattern": "^[0-9a-fA-F]{24}$" },仅"bsonType": "string"拦不住非法 ID 字符串
已有集合加验证前,先用 validationAction: "warn" 排查脏数据
对线上运行中的集合直接设 validationLevel: "strict",可能因历史数据不合规而批量写入失败。更安全的做法是分两步:
- 第一步:用
collMod设validationAction: "warn",观察日志里哪些操作触发了警告 - 第二步:修复或清洗问题文档,再把
validationAction改成"error" - 注意:
collMod修改validator后,旧文档不会自动重校验;只有后续修改才会触发,所以得靠应用层或脚本主动清理
最易被忽略的一点:验证规则一旦启用,就成为写入路径上的刚性关卡——它不关心你用的是 driver、shell 还是 Compass,也不区分 insert 还是 update,只要结构不匹配,writeConcern 再高也进不去。别指望“先写进去再修”,得在写入前就卡死。











