在findOneAndUpdate()的预处理钩子中修改mongoose文档

6
我有一个mongoose模式,如下所示:
var schema = new Schema({
    id:Number
    updated_at:Date
});

我正在使用findOneAndUpdate()来更新此模型,如下所示

model.findOneAndUpdate(
    { id: json.id },
    json,
    {
        upsert: true,
        runValidators: true
    })
    .then(() => {
        recordsUpdated++;
    })
    .catch((err) => {
        this.emit('error', err);
    });

传递给json的值不正确,我需要对其进行一些修改。我正在寻找一个预钩子来进行修改。我已经尝试过。

faction.pre('findOneAndUpdate', function (next) {
   this.update({ $set: { updated_at: this.getUpdate().updated_at * 1000 } });
   next();
});

简而言之,我想在更新数据库之前将以秒为单位的时间戳转换为毫秒,但这并不起作用。


在调用findOneAndUpdate之前,在中间件中修复json似乎是错误的做法:json.updated_at *= 1000; - JohnnyHK
可能可以。这个特定的用例可以在没有中间件的情况下完成。不过,了解如何实现这个过程仍然是很好的。 - Sayak Mukhopadhyay
3个回答

22

在盲目地四处乱扔石头后,对我有效的方法是

schema.pre('findOneAndUpdate', function (next) {
    this._update.updated_at *= 1000;
    next();
});

简而言之,需要修改位于_update属性中的文档。


我会等待其他可能比我的更好的答案。 - Sayak Mukhopadhyay
这在2019年仍然有效吗?@Sayak - Sumeet Kumar
@SumeetKumar 取决于 MongoDB 和 mongoose 的版本,我想。我不知道了,因为我再也没有在任何地方使用它了。 - Sayak Mukhopadhyay
我已经仔细查看了文档,寻找有用的内容,但没有成功,也没有找到任何关于this._update属性包含文档的信息。 - Sumeet Kumar
1
@SumeetKumar 我记得在文档中没有找到这个。我不得不手动检查对象的内容并找出一些东西。随着新版本的推出,可能会发生变化。我建议尝试一下,如果不成功,请尝试查看挂钩中 this 对象包含什么,然后从那里继续。 - Sayak Mukhopadhyay

0

更新 "mongoose": "^6.4.0"

多亏了上面评分最高的解决方案,对我有用的是

this._update.$set.updated_at = new Date();

在我的情况下,如果请求对象中存在 currency 键,我想将其保存为大写。
schema.pre('findOneAndUpdate', async function (next) {
  const currency = this?._update?.$set?.currency;
  if (currency) {
    this.set({ currency: currency.toUpperCase() });
  }
  next();
});

0
更好的解决方案是这样的:
schema.pre('findOneAndUpdate', function (this, next) {
    this.update().updated_at *= 1000;
    next();
});

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