如何使用 Mongoose 为每个文档插入触发一个函数?

问题描述 投票:0回答:1

我想在每次在集合中插入/创建元素时触发一个函数,而不是在更新元素时触发一个函数。 (我需要创建的元素的ID)

这就是我所做的:

schema.pre("save", function() {
    this.$locals.wasNew = this.isNew;
});

schema.post("save", function() {
    if (this.$locals.wasNew) {
        console.log(`User ${this.id} created!`);
    }
});

它适用于这样的呼叫:

await UserModel.create({
    mail
});

但不是这样的电话:

const user = await UserModel.findOneAndUpdate(
    { mail },
    { $set: { mail } },
    { new: true, upsert: true }
);

upsert
布尔值设置为 true 时,
save
似乎不会触发
isNew
钩子。

我做错了吗?遗漏了什么?或者有其他方法吗?

javascript mongodb mongoose
1个回答
0
投票

在 document.save 挂钩中不可能在 query.findOneAndUpdate 上执行相同的代码。原因是 document.save 中的钩子不会针对查询方法执行。欲了解更多,请参阅下面的链接1。

但是,有以下解决方法:

  1. 使用两个独立的方法 findById 和 save,原因是 findOneAndUpdate 实际上在做同样的事情。您也许可以在这里看到有关这些内容的原始讨论,参考链接 2.

  2. 使用变更流,参考链接3.

  3. 使用includeResultMetadata,参考链接4.

另请参阅下面选项 2 和 3 的示例代码。

const mongoose = require('/mongoose');
const { Schema } = mongoose;

run().catch((error) => console.log(error));
async function run() {
  await mongoose.connect('mongodb://127.0.0.1:27108', { replicaSet: 'rs' });
  const SomeModel = mongoose.model('Somemodel', new Schema({ key1: String }));
  await SomeModel.deleteMany();

  SomeModel.watch().on('change', (data) => {
    if (data.operationType == 'insert') {
      console.log(`change stream, new document, _id: ${data.fullDocument._id}`);
    }
  });

  await new SomeModel({ key1: 'key1 value 1' }).save();
  const doc2 = await SomeModel.findOneAndUpdate(
    { key1: 'xyz' },
    { key1: 'key1 value2' },
    { new: true, upsert: true, includeResultMetadata: true }
  );

  !doc2.lastErrorObject.updatedExisting &&
    console.log(`ResultMetadata, new document, _id: ${doc2.value._id}`);
}

输出:

change stream, new document, _id: 6643275fdb709107184e999a
ResultMetadata, new document, _id: 6643275f7550f5d65e7ba6a3
change stream, new document, _id: 6643275f7550f5d65e7ba6a3

链接

  1. 有关 findAndUpdate() 和查询中间件的注释

  2. findByIdAndUpdate 上不执行 pre、post 中间件 #964

  3. 更改直播

  4. 使用includeResultMetadata

© www.soinside.com 2019 - 2024. All rights reserved.