const person = await Person.findOne({firstName: "John", lastName: "Doe"});
person.previousDoc = person.toObject(); // create a deep copy of the previous doc
person.address = "123 Stack Road";
person.city = "Overflow";
person.state = "CA";
person.save();
然后在你的pre钩子中,你只需要引用_previousDoc的属性,比如:
// fallback to empty object in case you don't always want to check the previous state
const previous = this._previousDoc || {};
if (this.address !== previous.address) {
// do something
}
// you could also assign custom properties to _previousDoc that are not in your schema to allow further customization
if (previous.userAddressChange) {
} else if (previous.adminAddressChange) {
}
// Stores all of the old values of the instance into oldValues
const oldValues = {};
for (let key of Object.keys(input)) {
if (self[key] != undefined) {
oldValues[key] = self[key].toString();
}
// Saves the input values to the instance
self[key] = input[key];
}
yield self.save();
for (let key of Object.keys(newValues)) {
if (oldValues[key] != newValues[key]) {
// Do what you need to do
}
}
5条答案
按热度按时间lmvvr0a81#
接受的答案非常好用,也可以使用另一种语法,将setter内联到Schema定义中:
zf2sa74q2#
Mongoose允许您配置自定义设置器,在其中进行比较。pre('save')本身不会给予您所需的,但一起:
ojsjcaue3#
我一直在寻找一个解决方案来检测多个字段中的任何一个字段的变化。由于看起来你不能为完整的模式创建一个setter,所以我使用了一个虚属性。我只更新了几个地方的记录,所以这是一个非常有效的解决方案。
假设您的联系人搬家了,您需要更新他的地址:
然后在你的pre钩子中,你只需要引用_previousDoc的属性,比如:
型
bqujaahr4#
老实说,我尝试了这里发布的解决方案,但我必须创建一个函数,将旧值存储在数组中,保存值,然后查看差异。
nhhxz33t5#
我所做的是在预存路径中使用这个.构造函数来访问数据库中的当前值。
然后,您可以从oldData中获取您正在寻找的特定键,以便在您认为合适的时候使用:)
注意,这对于字符串这样的简单数据很有效,但是我发现对于子模式效果不好,因为mongoose内置了先运行的功能。因此,有时候对于子模式,你的oldData会与你的newData匹配。这可以通过给它自己的预保存路径来解决!