Mongoose 是不是提供对 pre('save') 中属性先前值的访问?
Posted
技术标签:
【中文标题】Mongoose 是不是提供对 pre(\'save\') 中属性先前值的访问?【英文标题】:Does Mongoose provide access to previous value of property in pre('save')?Mongoose 是否提供对 pre('save') 中属性先前值的访问? 【发布时间】:2012-07-11 06:32:50 【问题描述】:我想在pre('save')
中间件中将属性的新值/传入值与该属性的先前值(当前保存在数据库中的值)进行比较。
Mongoose 是否提供了执行此操作的工具?
【问题讨论】:
【参考方案1】:我一直在寻找一种解决方案来检测多个字段中任何一个字段的变化。由于看起来您无法为完整架构创建设置器,因此我使用了虚拟属性。我只更新了几个地方的记录,所以对于这种情况,这是一个相当有效的解决方案:
Person.virtual('previousDoc').get(function()
return this._previousDoc;
).set(function(value)
this._previousDoc = value;
);
假设您的 Person 移动了,您需要更新他的地址:
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)
【讨论】:
【参考方案2】:老实说,我尝试了此处发布的解决方案,但我必须创建一个函数,将旧值存储在数组中,保存值,然后查看差异。
// 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
【讨论】:
这不使用中间件,所以它不是对所提问题的回答【参考方案3】:接受的答案效果很好。也可以使用另一种语法,将 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();
);
【讨论】:
【参考方案4】: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();
)
【讨论】:
我是否需要这样做才能访问 validators 中的先前值?或者在验证器的情况下有更直接的方法? @aaronheckmann 很抱歉恢复了一个旧线程,我想这不会起作用,如果我们在负载均衡器后面有多个节点服务器。 @aaronheckmann 如果您使用的是 nginx,则有一个值可以指定主机,并将其发送到之前发送的同一服务器..或者您是如何解决的? 我不知道这是否曾经有效,但它不再有效。 this.name 未定义 我知道你写这篇 @JoshWoodcock 已经 4 年了,但我遇到了同样的问题。以上是关于Mongoose 是不是提供对 pre('save') 中属性先前值的访问?的主要内容,如果未能解决你的问题,请参考以下文章
Mongoose pre.save() 异步中间件未按预期工作
Mongoose pre.save() 异步中间件未按预期工作
bcrypt.hash() 的 next() 调用未触发 mongoose save 方法