鉴于架构:
{
widgets: [{
widget: {type: mongoose.Schema.Types.ObjectId, ref: 'widget'},
count: {type: Number}
}]
}
和申请路线:
在此设置中,如果我有2个并行请求执行相同操作,则2号检查都会通过,文档将保存2个小部件副本,即使这在我的业务逻辑中是“非法的”
异步流程如下:
我认为文档版本控制(__v
)会像过去那样为我解决这个问题,但显然我从来没有理解这一点,因为两个请求都是按顺序运行的,而我的调试器显示的是文档在两个预保存状态下都是X,在保存后状态下是X + 1。我不明白为什么不会抛出版本错误。
我认为这是一个需要解决的异步问题,不一定是严格的Mongoose,并且已经标记为这样。
编辑:这有效,但看起来非常冗长:
model
.findOneAndUpdate({
_id: doc._id,
__v: doc.__v
},
{
$push: {
widgets: {
widget: widget_id,
qty: 1
}
},
$inc: {
__v: 1
}
},
function(err, doc) {
// ...
});
另外,遗憾的是我无法更改现有文档,然后对其运行save()
方法。
我的搜索发现this bug,versionKey
在使用此方法时未自动增加versionKey
。我想我真的不理解ParseUser(json)
!
答案 0 :(得分:1)
看一下versionKey属性的解释(如果你还没有)
http://aaronheckmann.tumblr.com/post/48943525537/mongoose-v3-part-1-versioning
文章中的示例与您的类似,只是它们正在修改数组项(注释),并且您正在将新项目推送到窗口小部件数组。但据我所知,如果您使用mongoose v3 +并执行save()操作,这将为您执行所有必要的操作与versionKey。
所以,如果你做的事情如下:
model.findById(doc._id, function(err, doc) {
// handle error
doc.widgets.push({ widget: widget_id, count: widget_count });
doc.save(callback);
});
然后save()操作应该在内部看起来像这样:
doc.update(
{ _id: doc._id, __v: doc.__v },
{
$push: {
widgets: { widget: widget_id, count: widget_count }
},
$inc: {
__v: 1
}
}
);
所以也许你应该确保你使用mongoose v3 +并执行push()然后保存()或者你最初是这样做的?
我没有对此进行过测试,只是想与您分享我的搜索结果和想法,以防万一这会有所帮助。
答案 1 :(得分:0)
然后也许你可以尝试添加小部件检查更新查询:
model.findById(doc._id, function(err, doc) {
// handle error
// on update query check if there is no such widget in widgets array
doc.update(
{ _id: doc._id, { 'widgets.widget': { $nin: [widget_id] } }},
{
$push: {
widgets: { widget: widget_id, count: widget_count }
}
}
);
});