Typegoose v10中timestamps:true不生成createdAt/updatedAt字段问题
解决TypeGoose/Mongoose自动添加createdAt/updatedAt的问题
代码层面的正确配置(针对应用内创建/更新的文档)
方法1:继承TimeStamps类
从@typegoose/typegoose正确导入TimeStamps,让User类直接继承它,无需额外配置即可自动生成时间戳:
import { TimeStamps, getModelForClass } from '@typegoose/typegoose'; class User extends TimeStamps { // 自定义业务字段 public name!: string; public email!: string; } // 生成模型并使用 const UserModel = getModelForClass(User);
继承后,createdAt和updatedAt会自动挂载到模型上,执行save/updateOne等操作时会自动更新时间戳。
方法2:使用@modelOptions开启timestamps
如果不想继承类,直接在类上通过@modelOptions配置开启时间戳:
import { modelOptions, getModelForClass } from '@typegoose/typegoose'; @modelOptions({ schemaOptions: { timestamps: true, // 核心配置,启用自动时间戳 }, }) class User { public name!: string; public email!: string; } const UserModel = getModelForClass(User);
处理MongoDB Compass直接操作的文档
Compass是直接操作数据库,不会经过Mongoose中间件,因此需要在数据库层面处理时间戳自动生成:
1. 补全现有文档的时间戳
如果集合中已有旧文档,先通过MongoDB Shell批量补全字段:
// 切换到目标数据库 use your-database-name; // 给缺少createdAt的文档设置默认时间 db.users.updateMany( { createdAt: { $exists: false } }, { $set: { createdAt: new Date() } } ); // 补全updatedAt字段 db.users.updateMany( { updatedAt: { $exists: false } }, { $set: { updatedAt: new Date() } } );
2. 设置自动更新规则
本地MongoDB(用Change Stream监听)
创建一个持续运行的脚本,监听集合变化自动更新时间戳:
use your-database-name; const changeStream = db.users.watch(); changeStream.on('change', (event) => { const docId = event.documentKey._id; switch (event.operationType) { case 'insert': db.users.updateOne( { _id: docId }, { $set: { createdAt: new Date(), updatedAt: new Date() } } ); break; case 'update': case 'replace': db.users.updateOne( { _id: docId }, { $set: { updatedAt: new Date() } } ); break; } });
这个脚本需要保持运行,你可以将其封装为后台服务。
MongoDB Atlas(用内置触发器)
在Atlas控制台创建触发器:
- 触发条件选择
users集合的插入/更新操作 - 触发器函数内容如下:
exports = async function(changeEvent) { const collection = context.services.get("你的集群名称").db("你的数据库名").collection("users"); const docId = changeEvent.documentKey._id; if (changeEvent.operationType === "insert") { await collection.updateOne( { _id: docId }, { $set: { createdAt: new Date(), updatedAt: new Date() } } ); } else if (changeEvent.operationType === "update" || changeEvent.operationType === "replace") { await collection.updateOne( { _id: docId }, { $set: { updatedAt: new Date() } } ); } };
额外检查点
- 你的版本组合是兼容的:TypeGoose v10确实适配Mongoose v6.x,无需调整版本。
- 只有新创建的文档会自动生成时间戳,旧文档需要手动补全(上述Shell命令可处理)。
- 确保应用内始终使用TypeGoose生成的
UserModel操作文档,而非Mongoose原生模型。
内容的提问来源于stack exchange,提问作者Avishka Dambawinna
相关产品推荐
相关产品推荐

