You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止Mongoose save()覆盖自定义设置的updatedAt字段?

解决Mongoose save()覆盖手动设置的updatedAt字段问题

这个问题我之前也碰到过——因为你在Schema里启用了timestamps选项,Mongoose默认会在每次调用save()时自动把updatedAt刷新为当前时间,哪怕你手动设置过它的值。下面给你几个实用的解决方案:

1. 单次保存时临时禁用自动时间戳

这是最直接的临时处理方式,在调用save()的时候传入{ timestamps: false }选项,告诉Mongoose这次不要自动更新时间戳:

// 手动设置updatedAt之后,保存时加上timestamps: false参数
await applicant.save({ timestamps: false });

这样你手动设置的updatedAt就会被完整保留,不会被覆盖。适合只需要在个别测试用例或操作里跳过自动更新的场景。

2. 自定义时间戳更新逻辑(全局控制)

如果需要更灵活的全局规则——比如只有当updatedAt没有被手动修改时才自动更新,可以给Schema添加一个pre('save')钩子:

const DataSchema: Schema = new Schema({
  user_name: { type: String, required: true },
  uuid: { type: String, required: true },
  status: { type: String, required: true, default: "unprocessed" },
  request_origin: { type: String, required: true }
}, { timestamps: { createdAt: "createdAt", updatedAt: "updatedAt" } });

// 添加pre-save钩子,判断是否手动修改过updatedAt
DataSchema.pre('save', function(next) {
  // 如果已经手动修改过updatedAt,直接跳过自动更新逻辑
  if (this.isModified('updatedAt')) {
    return next();
  }
  // 否则保持默认的自动更新行为
  this.updatedAt = new Date();
  next();
});

这个钩子会在保存前检查updatedAt是否被手动改动过,如果是的话就不执行自动更新,完全保留你设置的值。

3. 用更新操作代替save()(测试场景适配)

在单元测试场景里,也可以直接用updateOne或findOneAndUpdate来设置字段,绕开save()的自动时间戳机制:

// 先创建基础文档
await DataModel.create({
  "user_name": "user_notifying2rejected",
  "uuid": "10",
  "status": "notifying_user",
  "request_origin": "127.0.0.10"
});

// 直接更新指定文档的updatedAt字段
await DataModel.updateOne(
  { uuid: "10" },
  { updatedAt: new Date(new Date() - 2.592e+8) }
);

这种方法适合不需要先实例化文档,直接修改数据库中字段的测试场景。

内容的提问来源于stack exchange,提问作者oneturkmen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:39:28