我有一个具有以下结构的文档,为简洁起见省略了一些字段;
{
_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是有意义的。我还在插入时将人员字段默认设置为空数组,但尚未分配管理员。以下是重构后我的架构的样子;
{
_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并不提供原始操作的非移位功能,但是$position
实现了相同的效果。因此,我不再需要状态,因为所有当前管理器都将位于阵列的第0位。此外,我不需要endDate,因为我可以轻松地从之前的经理文档中获取该日期。希望这有助于某人:)
答案 0 :(得分:1)
与您当前的架构保持一致(不推荐):
首先,将整个文档保存到客户端:
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}})
毕竟,我建议您在管理人员阵列中放弃状态字段。创建一个名为currentManager
的新字段。这样做有以下几点:
它消除了您必须付出的努力以保持状态字段互斥
这使得找到当前的经理非常容易(没有$elemMatch
)
它更有意义,因为管理器subdoc的PK不是管理器,而是managerId,startDate和endDate的联合键。
或者,摆脱状态字段&amp;不转移新经理而不是推动。然后,您知道字段0始终具有当前(如果存在)。