javascript - 在 MongoDB 中使用嵌入式文档

标签 javascript mongodb meteor

我有一个具有以下结构的文档,为简洁起见省略了一些字段;

{
  _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/

相关文章:

javascript - 导航菜单没有正确的动画

mongodb - 如何查询包含嵌套数组子集的 mongo 文档

javascript - Jquery - 使用带有 .click 和 'this' 的函数

javascript - 解析firebase对象javascript

javascript - 如何处理调用同一函数的多个 Ajax 调用?

javascript - Meteor:显示以天分隔的文档

mongodb - 是否有将 AWS lightsail mongoDB 与 mongo Compass 连接的过程?

mongodb - 如何在elasticsearch中索引时进行映射

javascript - Meteor 中的简单架构错误

javascript - 当订阅已经限制了数据集时,是否有必要将限制传递给数据?