【问题标题】:Update many sub of sub-document array using $set / $push使用 $set / $push 更新子文档数组的许多子
【发布时间】:2020-09-08 22:58:19
【问题描述】:

以下是示例工作区文档。我想在前端拖放时更新框位置。

{
"_id": ObjectId("5eaa9b7c87e99ef2430a320b"),
"logo": {
    "url": ".../../../assets/logo/dsdsds.png",
    "name": "testUpload"
},
"name": "My World",
"sections": [{
        "box": [{
                "_id": ObjectId("5da87b33502d6c634b3aa7ce"),
                "name": "Meran To",
                "position": 0
            },
            {
                "_id": ObjectId("5da87b33502d6c7d873aa7d0"),
                "name": "Documentation",
                "position": 2
            },
            {
                "_id": ObjectId("5da87b33502d6cdbb93aa7cf"),
                "name": "File Manager Upload File Drive",
                "position": 1
            },
            {
                "_id": ObjectId("5da87b33502d6c276a3aa7cd"),
                "name": "File Manager Upload File Drive",
                "position": 1
            }
        ],
        "id": 1,
        "title": "Simplicity",
        "description": "Follow your barriers"
    },
    {
        "box": [],
        "id": 2,
        "title": "xfxdfxcx 34",
        "description": "sdsdsd sfsfsd ewrewrewre"
    }
]
}

我通过API将更新后的位置从前端发送到后端,如下图所示。

[
 {
   "id": "5da87b33502d6c634b3aa7ce",
   "position": 0
 }, {
   "id": "5da87b33502d6c7d873aa7d0",
   "position": 1
 }, {
   "id": "5da87b33502d6cdbb93aa7cf",
   "position": 2
 }, {
   "id": "5da87b33502d6c276a3aa7cd",
   "position": 3
}]

我目前正在使用以下代码更新数据库

for (const el of req.body) {
  await this.model.updateOne({
    _id: req.params.workspaceId,
    sections: {
        $elemMatch: {
            id: req.params.sectionId
        }
    },
    'sections.box': {
        $elemMatch: {
            _id: el.id
        }
    },
  }, {
    $set: {
        'sections.$[outer].box.$[inner].position': el.position
    }
  }, {
    arrayFilters: [{
        'outer.id': req.params.sectionId
    }, {
        'inner._id': el.id
    }],
    upsert: false,
  });
}

但这不是最好的方法,它会多次命中数据库。 所以我需要用猫鼬查询本身优化这段代码。 可能正在使用 $set / $push。我不知道任何确切的方法。

所以基本上我们需要移除外部的 for 循环并使其与 mongoose 本身一起工作。这是我的要求。

提前感谢大家的支持。

【问题讨论】:

    标签: node.js mongodb typescript express mongoose


    【解决方案1】:

    有两种方法可以做到。

    1. 批量写入

      const bulkOps = [];
      req.body.forEach((el) => {
          const upsertDoc = {
              updateOne: {
                  filter: {
                    _id: req.params.workspaceId,
                    sections: {
                      $elemMatch: {
                        id: req.params.sectionId
                      }
                    },
                   'sections.box': {
                      $elemMatch: {
                        _id: el.id
                    }
                 },
             },
             update: {
               $set: {
                  'sections.$[outer].box.$[inner].position': el.position
               }
             },
             arrayFilters: [{
               'outer.id': req.params.sectionId
             }, {
              'inner._id': el.id
             }],
             upsert: false,
          }
        };
      
        bulkOps.push(upsertDoc);
      });
      
      const result = await this.model.collection.bulkWrite(bulkOps);
      
    2. 批量更新

       const bulkUpdate = this.model.collection.initializeUnorderedBulkOp();
       req.body.forEach((el) => {
         bulkUpdate.find({
               _id: req.params.workspaceId,
               sections: { $elemMatch: { id: req.params.sectionId } },
               'sections.box': { $elemMatch: { _id: el.id } },
           }).arrayFilters([{ 'outer.id': req.params.sectionId }, { 'inner._id': el.id }])
           .updateOne({ $set: { 'sections.$[outer].box.$[inner].position': el.position } 
         });
       });
       await bulkUpdate.execute();
      

    【讨论】:

      猜你喜欢
      • 2019-05-25
      • 2018-01-02
      • 1970-01-01
      • 2018-05-28
      • 2016-11-04
      • 2016-11-23
      • 2017-03-31
      • 2019-06-21
      • 1970-01-01
      相关资源
      最近更新 更多