Javascript 在MongoDB中使用嵌入式文档
我有一个具有以下结构的文档,为了简洁起见省略了一些字段Javascript 在MongoDB中使用嵌入式文档,javascript,mongodb,meteor,Javascript,Mongodb,Meteor,我有一个具有以下结构的文档,为了简洁起见省略了一些字段 { _id: 1, projectName: name, managers: [ { managerId: manager1, status: false, startDate: startDate, endDate: endDate }, { managerId: manager2, status: false, startDate: startDate, endDate: endDate } { ma
{
_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,以及是否未将新文档推入
{
_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,因为我可以很容易地从以前的经理的文档中获得它。希望这对某人有所帮助:)符合您当前的模式(不推荐):
首先,将整个文档保存到客户端:
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;
}
使用新文档更新文档:
Collection.update(1, doc)
或者,如果您真的非常关心发送几个额外的字节:
Collection.update(1, {$set: {managers: doc.managers}})
在所有这些之后,我建议您放弃管理器数组中的status字段,创建一个名为currentManager
的新字段。这样做可以做几件事:
- 它消除了您为保持状态字段互斥而必须付出的努力
- 这使得查找当前管理器非常容易(无
)$elemMatch
- 这更有意义,因为managers子文档的主键不是manager,而是managerId、startDate和endDate的联合键
或者,去掉status字段&取消新经理的职位,而不是推。然后,您知道字段0始终具有当前值(如果存在)。当然是两次更新。使用
“managers.0”:{“$exists”:false}
作为其他更新的“空数组”测试条件。如果该语句没有更新,则执行另一个更新。
Collection.update(1, {$set: {managers: doc.managers}})