防止Mongoose的findOneAndUpdate方法更改updatedAt字段

19

我使用Mongoose模型进行了更新,并使用$inc操作符检索该模型,实现了简单的视图计数器:

const profile = await Profile.findOneAndUpdate({ userName }, { $inc: { viewsCount: 1 } });

Profile 模式启用了 timestamps 选项。问题是,在更新 viewsCount 期间会更新 updatedAt,这不是期望的行为。

我希望在尽可能少的查询情况下禁用在更新 viewsCount 时更新 updatedAt

我假设 Mongoose 时间戳是通过 pre-hooks 实现的。

如何让 findOneAndUpdate 在不更新 updatedAt 的情况下增加 viewsCount

可以通过否定时间戳钩子的效果来实现吗?

有类似的问题解决了更新 updatedAt 的问题,但解决方案不适用于该情况。


请跳过Mongoose中某些更新的时间戳中间件。 - danii
3个回答

19

mongoose 5.9.3 开始,你可以将第三个参数设置为 { timestamps: false }

来自 文档

[options.timestamps=null] «Boolean» 如果设置为 false 并且模式级别的时间戳已启用,则跳过此更新的时间戳。请注意,这允许您覆盖时间戳。如果未设置模式级别时间戳,则不执行任何操作。


5
在查阅了Mongoose文档后,简短回答是不行,没有办法在调用findOneAndUpdate()时不设置updatedAt字段。如果您查看此处的文档,可以明确看到更新操作(findOneAndUpdate()、update()和bulkWrite())中所有函数都会在查询中添加$set运算符以设置updatedAt。话虽如此,您还有另一种选择,我强烈建议您使用。
解决方法:
直接向模型添加createdAt和updatedAt字段,并删除时间戳。当然,Mongoose为您处理它非常方便,但最终如果您必须尝试更改特定用例的时间戳设置功能,那么最好自己实现。
如果您喜欢在调用.save()或.update()时设置updatedAt和createdAt,您总可以编写自己的中间件来添加这些操作。
ProfileSchema.pre('save', function(next) {
  this.createdAt = Date.now();
  this.updatedAt = Date.now();
  next();
});

我知道这不是理想的解决方案,但坦白地说,我发现它更有用,因为它可以提供更多的控制,并且可以减少Mongoose的意外行为。你对自己代码越有控制力,就越好。希望这有所帮助!


谢谢。我希望有更简洁的解决方案。一个适当的时间戳实现并不那么简单。我可能会分叉第三方时间戳插件。 - Estus Flask
我维护了默认的时间戳:{ createdAt: Date.now, updatedAt: 'last_written' },以便知道我何时执行管理员职责以及记录何时更新。如果想要知道记录何时更新,那么我会手动创建另一个updatedAt时间戳进行维护。自动最后更新的时间戳非常有用。我不建议去除它。 - Someone Special

2
我已将createdAt设置为不可变。这样,即使我们在集合中编辑相关文档并设置updatedAt字段以使用new Date()获取当前时间戳,它也无法更新。对我来说,这个方法效果很好。请查看下面的代码片段。
createdAt: {
  type: Date,
  immutable: true,
  default: Date.now
},
updatedAt: {
  type: Date,
  default: new Date()
}

我已将时间戳设置为true。
请检查与上述代码片段相关的总体模式。
const projectSchema = mongoose.Schema({
  name: {
    type: String,
    requied: true
  },
  description: {
    type: String,
    required: true
  },
  owner: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "User"
  },
  createdAt: {
    type: Date,
    immutable: true,
    default: Date.now
  },
  updatedAt: {
    type: Date,
    default: new Date()
  }
}, {
  timestamps:true
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接