我想在每次在集合中插入/创建元素时触发一个函数,而不是在更新元素时触发一个函数。 (我需要创建的元素的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
钩子。
我做错了吗?遗漏了什么?或者有其他方法吗?
在 document.save 挂钩中不可能在 query.findOneAndUpdate 上执行相同的代码。原因是 document.save 中的钩子不会针对查询方法执行。欲了解更多,请参阅下面的链接1。
但是,有以下解决方法:
使用两个独立的方法 findById 和 save,原因是 findOneAndUpdate 实际上在做同样的事情。您也许可以在这里看到有关这些内容的原始讨论,参考链接 2.
使用变更流,参考链接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
链接