mongodb不支持schema层default声明,默认值必须由应用层控制。可通过插入前手动补全字段、$setoninsert配合upsert、或json schema default元数据辅助校验后手动填充实现。

MongoDB 本身不支持像 SQL 那样在 schema 层声明 DEFAULT 值(比如 MySQL 的 CREATE TABLE ... name VARCHAR(32) DEFAULT 'unknown'),所以“设置默认值”这件事必须由应用层或服务层主动控制,不能靠数据库自动填充。
insertOne / insertMany 时手动补全字段
这是最直接、最可控的方式。写入前检查文档中是否缺失关键字段,再用代码补上默认值。
- Python 示例(PyMongo):
doc = {"name": "张三"} if "status" not in doc: doc["status"] = "active" if "created_at" not in doc: doc["created_at"] = datetime.utcnow() collection.insert_one(doc) - Node.js 示例(MongoDB Driver):
const doc = { name: "李四" }; Object.assign(doc, { status: doc.status ?? "pending", version: doc.version ?? 1, updated_at: new Date() }); collection.insertOne(doc); - 注意:不要依赖
??或||判断null/undefined—— 如果字段显式设为0、false或空字符串,||会误判为“不存在”
用 $setOnInsert + upsert 模拟默认值
当你用 updateOne 配合 upsert: true 时,可以借助 $setOnInsert 在文档首次插入时才设置字段,后续更新不影响它。
- 适用场景:用户注册后首次写入 profile,但之后允许修改;或日志类文档只在创建时打时间戳
- 示例(shell):
db.users.updateOne( { _id: "u1001" }, { $set: { name: "王五", last_login: new Date() }, $setOnInsert: { created_at: new Date(), role: "user", score: 0 } }, { upsert: true } ) - ⚠️ 注意:
$setOnInsert只在真正插入新文档时生效;如果匹配到已有文档,这部分会被忽略
Schema 验证 + default 字段(4.4+ 支持)
MongoDB 4.4 开始,在 collMod 或 createCollection 时可通过 JSON Schema 的 default 关键字声明默认值,但它**仅用于验证,不自动填充** —— 这点极易误解。
- 你写:
db.createCollection("products", { validator: { $jsonSchema: { bsonType: "object", properties: { price: { bsonType: "double", default: 99.99 } } } } }) - 结果是:MongoDB 不会把
price自动设为99.99;它只在你显式传入price: null或类型不符时触发校验失败 - 真正能起作用的是配合应用层逻辑:先做
validate,再根据 schema 中的default字段手动补值 —— 它只是个元数据,不是执行器
最容易被忽略的一点是:ObjectId 类型的 _id 虽然“默认生成”,但它不是“默认值”,而是写入时缺失 _id 字段的 fallback 行为;一旦你显式传入 _id: null 或 _id: undefined,MongoDB 仍会报错,不会退回到自动生成。所以任何“默认”逻辑,都得在业务代码里稳稳地做一次判断和赋值。











