我使用的是MongoDB 3.0(为了清晰起见,而不是3.2),我想将一个对象卸载到一个数组中。我的主模式是client
,其子模式为opportunities
,并且在opportunitiesUpdates
的另一个子模式下。
我的对象,以及opportunities
子架构中的数组,包含文本和数字字段以及其他对象。
机会架构:
var opportunitiesSchema = new mongoose.Schema({
// removed other fields for bevity
updates: [opportunitiesUpdates]
});
OpportunitiesUpdates架构:
var opportunitiesUpdates = new mongoose.Schema({
by: {
userName: String,
realName: String
},
when: {type: Date, default: null},
description: String
});
我使用Mongoose 4.x作为我的ODM。
我现有的代码是:
Client.findOne(
{'_id': { $in: [clientId] }, 'opportunities._id': { $in: [opportunityId] }},
function(err, client){
if (err) {
return res.status(400).json(err);
} else {
var opportunity = _.find(client.get('opportunities'), function(o){
return o._id == opportunityId
}); // _.find
opportunity.updates.unshift(body); // body is escaped req.body
client.save(function(err){
return res.status(200).json(client);
}); // client.save
} // if
} // function
); // Client.findOne
Vars clientId
,opportunityid
和body
都是之前定义的。此代码工作正常,并进行正确的更新。找到了正确的客户文档,正确的机会文档位于数组中,感谢lodash的.find
,更新未移至updates
数组,然后保存
但是这不是MongoDB在进行更改时锁定集合的一个原子事务,在一次转换中完成整个更改(unshift),使文档处于最终所需状态。
有一个事务,其中找到了文档(.findOne
),然后进行了一些计算,更新了文档,然后将其作为第二个事务保存回来(.save
)
有没有办法可以用一个MongoDB事务做到这一点?否则,.findOneAndUpdate
与$push
或$set
一起使用,但我似乎无法在此处工作。我查看了28360526和7936019,但无法按照我想要的方式开展此工作 - $each
和$position: 0
看起来应该开展业务但它只是用对象的内容覆盖整个数组而不是不移位。
在这里,性能并不重要,因为没有对机会进行多次更新,因此处理时间的几分钟不是关键,关键是原子性和避免种族风险条件。
有什么建议吗?我错过了什么?