我有一个具有以下结构的文档,为简洁起见省略了一些字段;
{
_id: 1,
projectName: name,
managers: [
{ managerId: manager1, status: false, startDate: startDate, endDate: endDate },
{ managerId: manager2, status: false, startDate: startDate, endDate: endDate }
{ managerId: manager3, status: true, startDate: startDate, endDate: endDate }
]
}
这是我的业务规则;
- 可以在指定或不指定经理的情况下创建项目
- 可以为经理分配/重新分配项目 - 项目可以在经理之间转移
- 每个项目都应该有相关经理的足迹
- 一个项目不能同时有多个经理
我的意图是;
重新分配官员后,将当前事件经理的状态设置为 false,然后使用单个查询将新经理推送到嵌入式文档中,因为与两次不同,单次往返数据库最有意义往返。 以下是我想出的一个片段;
Collection.update( { _id: 1, "managers.status": true }, { $set: { "managers.$.status": false }, $push: { managers: { managerId: newManagerId, status: true, startDate: startDate, endDate: endDate } } } );
挑战
由于以下情况,我的意图成为挑战;
创建没有经理的新项目时,不设置包含嵌入式经理文档的经理字段
如何检查状态为 true 的嵌入文档是否存在,以便我可以将其设置为 false 以及它是否不推送新文档
有什么想法吗?
更新
引用@Matt K 的回复,对我的架构做出一些更好的设计决策并使用 unshift 而不是 push 是有意义的。我还将 officers 字段默认设置为插入时的空数组,以防尚未分配经理。以下是我的架构在重构后的样子;
{
_id: 1,
projectName: name,
managers: [
{ managerId: manager1, startDate: startDate },
{ managerId: manager2, startDate: startDate }
{ managerId: manager3, startDate: startDate }
]
}
这是我的查询;
Collection.update(
{ _id: 1 },
{
$push: {
managers: {
$each: [{ managerId: newManagerId, startDate: startDate }],
$position: 0
}
}
}
);
注意 Mongo API 不提供 unshift 作为原子操作,但有 $position
实现相同的效果。所以我不再需要状态,因为所有当前管理器都将位于数组的位置 0。此外,我不需要 endDate,因为我可以轻松地从前任经理的文档中获取它。希望这对某人有帮助:)
最佳答案
与您当前的架构保持一致(不推荐):
首先将整个文档保存到客户端:
doc = {
_id: 1,
projectName: name,
managers: [
{ managerId: "manager1", status: false, startDate: "startDate", endDate: "endDate" },
{ managerId: "manager2", status: false, startDate: "startDate",endDate: "endDate" },
{ managerId: "manager3", status: true, startDate: "startDate", endDate: "endDate" }
]
}
如果经理字段不存在则添加:
doc.managers = doc.managers || [];
然后,遍历每个字段,将状态设置为 false:
for (var i = 0; i < doc.managers.length; i++) {
doc.managers[i].status = false;
}
推送新经理:
doc.managers.push({
managerId: "newManagerId", status: true, startDate: "startDate", endDate: "endDate"
})
用你的新文档更新文档:
Collection.update(1, doc)
或者,如果您真的非常关心发送几个额外的字节:
Collection.update(1, {$set: {managers: doc.managers}})
毕竟,我建议您放弃 managers 数组中的状态字段并创建一个名为 currentManager
的新字段。这样做有几件事:
它消除了您为保持状态字段相互排斥而必须付出的努力
它让找到当前经理变得非常容易(没有
$elemMatch
)这更有意义,因为您的经理子文档的 PK 不是经理,而是 managerId、startDate 和 endDate 的联合键。
或者,摆脱状态字段并取消转移新经理而不是插入。然后,您知道字段 0 始终具有当前(如果存在)。
关于javascript - 在 MongoDB 中使用嵌入式文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30916219/