Node.js $push和$set在一个数组中设置相同的子文档
我试图用MongooseJS4.9.5和Mongo3.2.7在子文档数组中保存状态的历史记录 文档结构示例:Node.js $push和$set在一个数组中设置相同的子文档,node.js,mongodb,mongoose,Node.js,Mongodb,Mongoose,我试图用MongooseJS4.9.5和Mongo3.2.7在子文档数组中保存状态的历史记录 文档结构示例: 公司(架构) 员工(架构):[] 当前状态:字符串 状态(模式):[] 状态:字符串 开始日期:日期 完:日期 当我更改employee状态时,我想更改currentState,将新状态添加到states数组中,并更新定义“ends”时间戳的最后一个状态 // I get the last state position from a previous find request
- 公司(架构)
- 员工(架构):[]
- 当前状态:字符串
- 状态(模式):[]
- 状态:字符串
- 开始日期:日期
- 完:日期
// 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}
- 有没有建议如何避免为此运行两个更新
- 避免存储“结束”日期,但能够根据数组中下一项的“开始”计算结束日期的任何解决方法
谢谢,我希望其他地方已经回答了这个问题,但似乎没有其他合理的回答。如前所述,您实际上无法在单个更新操作中执行此操作,因为操作在同一路径上“冲突”。但允许在单个请求和响应中应用“多个更新”
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
}
}
}
}}
])
现在当然不会像以前那样返回“修改过的文档”。因此,如果您需要实际返回文档,则需要添加到承诺链:
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);
})
当然要注意的是,在应用和执行时,“可能”会对文档进行另一次修改。但这就是你正在做的手术的成本
<>通常最好考虑如果你真的<强>需要< /强>返回的文档。在大多数情况下,您只是已经拥有了信息和您应该知道的任何“更新”,因为您正在“发布它们”,如果您想要“真正的反应”,那么您应该通过套接字监听数据上的其他更改事件
注意您可以简单地将“多个”调用“链接”,但这实际上是来自服务器的“多个”调用和响应,而不是使用一个。所以不这样做真的没有什么好处
这是《国家历史》的一部分。update语句中的操作应用程序没有“顺序”。因此,您不能修改相同的路径。您应该改为使用
.bulkWrite()
并在两个单独的操作中在“同一路径”上发出$set
和$push
。它们需要分开,但“批量”所做的是作为一个请求和一个响应发送,而不是每个请求“多个”。谢谢Neil,非常感谢!