我试图用mongoosejs 4.9.5和mongo 3.2.7保存子文档数组中的状态历史
文档结构示例:
当我更改员工状态时,我想要更改currentState,将新状态添加到states数组中,并更新最后一个状态以定义'结束'时间戳
// I get the last state position from a previous find request
var lastStateIndex = employee.stateHistory.length - 1;
var changeStateDate = new Date();
// Prepare the update
var query = { _id: companyId, "employees._id": employeeId };
var update = {
$set: {
"employees.$.state": newState,
`employees.$.stateHistory.${lastStateIndex}.ends`: changeStateDate
},
$push: {
"employees.$.stateHistory": {
state: newState,
starts: changeStateDate
}
}
}
Company.findOneAndUpdate(query, update, { multi:false, new:true}, ... )
Mongo正在返回以下错误
{"name":"MongoError","message":"Cannot update 'employees.0.stateHistory.0.ends' and 'employees.0.stateHistory' at the same time","ok":0,"errmsg":"Cannot update 'employees.0.stateHistory.0.ends' and 'employees.0.stateHistory' at the same time","code":16837}
谢谢,
答案 0 :(得分:1)
我预计这已在其他地方得到解答,但似乎没有其他合理的回应。如评论所述,您无法在单个更新操作中实际执行此操作,因为操作"冲突"在同一条路上。但.bulkWrite()
允许"多次更新"要应用于单个请求和响应。
Company.bulkWrite([
{ "updateOne": {
"filter": { "_id": companyId, "employees._id": employeeId },
"update": {
"$set": {
"employees.$.state": newState,
[`employees.$.stateHistory.${lastStateIndex}.ends`]: changeStateDate
}
}},
{ "updateOne": {
"filter": { "_id": companyId, "employees._id": employeeId },
"update": {
"$push": {
"employees.$.stateHistory": {
"state": newState,
"starts": changeStateDate
}
}
}
}}
])
现在当然.bulkWrite()
不会返回"修改后的文档"像.findOneAndUpdate()
那样。因此,如果您需要实际返回文档,则需要添加到Promise链中:
Company.bulkWrite([
{ "updateOne": {
"filter": { "_id": companyId, "employees._id": employeeId },
"update": {
"$set": {
"employees.$.state": newState,
[`employees.$.stateHistory.${lastStateIndex}.ends`]: changeStateDate
}
}},
{ "updateOne": {
"filter": { "_id": companyId, "employees._id": employeeId },
"update": {
"$push": {
"employees.$.stateHistory": {
"state": newState,
"starts": changeStateDate
}
}
}
}}
]).then( result => {
// maybe inspect the result
return Company.findById(companyId);
})
当然注意到它是可能的"在应用.bulkWrite()
并执行.findById()
时,可以对文档进行另一次修改。但这就是你正在进行的操作的成本。
通常最好考虑您是否需要返回的文档。在大多数情况下,您只需拥有信息和任何更新"你应该知道,因为你是"发布它们",如果你想要"真正反应"那么你应该通过套接字监听数据上的其他变化事件。
注意你可以简单地"链" "倍数"
.findOneAndUpdate()
来电,但这确实是多次"来自服务器的呼叫和响应,而不是使用.bulkWrite()
的一个。否则,除此之外无法获得任何好处。