使用$ set / $ push更新子文档数组的许多子项

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用$ set / $ push更新子文档数组的许多子项相关的知识,希望对你有一定的参考价值。

下面是示例工作区文档。当我们在前端拖放时,我想更新框的位置。

{
"_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循环并使其与猫鼬本身一起工作。这是我的要求。

谢谢您的支持。

答案

有两种方法。

  1. bulkWrite

    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. bulkUpdate

     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();
    

以上是关于使用$ set / $ push更新子文档数组的许多子项的主要内容,如果未能解决你的问题,请参考以下文章

Mongodb怎样更新像这样的文档,数组里面有子文档

mongodb_修改器($inc/$set/$unset/$push/$pop/upsert......)

mongodb_修改器($inc/$set/$unset/$push/$pop/upsert......)

mongodb_修改器($inc/$set/$unset/$push/$pop/upsert......)

学习mongo系列修改器($inc/$set/$unset/$push/$pop/upsert)

使用 Mongoose 更新数组中的子文档