mongodb Mongoose是否提供对pre('save ')中属性先前值的访问?

pvcm50d1  于 2022-12-18  发布在  Go
关注(0)|答案(5)|浏览(98)

我想在pre('save')中间件中比较属性的新值/传入值与该属性的先前值(当前保存在数据库中)。
Mongoose是否提供了执行此操作的设备?

lmvvr0a8

lmvvr0a81#

接受的答案非常好用,也可以使用另一种语法,将setter内联到Schema定义中:

var Person = new mongoose.Schema({
  name: {
    type: String,
    set: function(name) {
      this._previousName = this.name;
      return name;
    }
});

Person.pre('save', function (next) {
  var previousName = this._previousName;
  if(someCondition) {
    ...
  }
  next();
});
zf2sa74q

zf2sa74q2#

Mongoose允许您配置自定义设置器,在其中进行比较。pre('save')本身不会给予您所需的,但一起:

schema.path('name').set(function (newVal) {
  var originalVal = this.name;
  if (someThing) {
    this._customState = true;
  }
});
schema.pre('save', function (next) {
  if (this._customState) {
    ...
  }
  next();
})
ojsjcaue

ojsjcaue3#

我一直在寻找一个解决方案来检测多个字段中的任何一个字段的变化。由于看起来你不能为完整的模式创建一个setter,所以我使用了一个虚属性。我只更新了几个地方的记录,所以这是一个非常有效的解决方案。

Person.virtual('previousDoc').get(function() {
  return this._previousDoc;
}).set(function(value) {
    this._previousDoc = value;
});

假设您的联系人搬家了,您需要更新他的地址:

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) {

}

bqujaahr

bqujaahr4#

老实说,我尝试了这里发布的解决方案,但我必须创建一个函数,将旧值存储在数组中,保存值,然后查看差异。

// 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
    }
}
nhhxz33t

nhhxz33t5#

我所做的是在预存路径中使用这个.构造函数来访问数据库中的当前值。

const oldData = this.constructor.findById(this.id)

然后,您可以从oldData中获取您正在寻找的特定键,以便在您认为合适的时候使用:)

let name = oldData.name

注意,这对于字符串这样的简单数据很有效,但是我发现对于子模式效果不好,因为mongoose内置了先运行的功能。因此,有时候对于子模式,你的oldData会与你的newData匹配。这可以通过给它自己的预保存路径来解决!

相关问题