如何用MongoDB的findOneAndUpdate更新嵌套数组内的嵌套对象
更新MongoDB中嵌套数组内的嵌套对象字段
需求说明
需要更新文档中client_Username为elsa的客户端下,指定documents对象的doc_upload字段。
现有文档结构
[ { _id: ObjectId("637c648fb8fcfb2bc3071bb9"), consultant_name: "Sam letterman", consultantUsername: "sam", consultant_Password: "123", type: "consultant", clients: [ { client_name: "john", client_Username: "mouh", client_Password: "123", type: "client", documents: [ { name: "Acte de mariage", description: "copie conforme certifié du certificat de mariage", doc_upload: "", _id: ObjectId("637c648fb8fcfb2bc3071bbe") }, { name: "Acte de de divorce", description: "because divorced", doc_upload: "", _id: ObjectId("637c648fb8fcfb2bc3071bbf") } ] }, { _id: ObjectId("637c648fb8fcfb2bc3071bb9"), client_name: "narrakech", client_Username: "elsa", client_Password: "123", type: "client", documents: [ { name: "Acte de mariage", description: "copie conforme certifié du certificat de mariage", doc_upload: "", _id: ObjectId("637c648fb8fcfb2bc3071bbe") }, { name: "Acte de de divorce", description: "Parce que qu'on est shizo", doc_upload: "", _id: ObjectId("637c648fb8fcfb2bc3071bbf") } ] } ], createdAt: ISODate("2022-11-22T05:56:31.469Z"), updatedAt: ISODate("2022-11-27T03:40:31.835Z"), __v: 0 } ]
当前可行的client层级更新代码
router.put('/:id', async (req, res) => { if (cond) { try { const updatedUser = await User.findOneAndUpdate( { 'clients._id': req.params.id }, { $set: { 'clients.$.client_name': 'narrakech' } }, { new: true } ); res.status(200).json(updatedUser); } catch (err) { res.status(500).json(err); } } else { res.status(401).json('You can update only your account.'); } })
解决方案:使用数组过滤器(arrayFilters)
单靠$操作符只能定位到外层clients数组的匹配元素,无法深入内层documents数组。MongoDB提供了arrayFilters参数,可以定义内层数组的匹配条件,实现精准更新。
场景1:根据document的_id更新
假设要更新elsa下_id为ObjectId("637c648fb8fcfb2bc3071bbe")的document的doc_upload字段,代码如下:
router.put('/update-doc', async (req, res) => { if (cond) { try { const updatedUser = await User.findOneAndUpdate( // 匹配client_Username为elsa的外层文档 { 'clients.client_Username': 'elsa' }, // 使用$$doc引用arrayFilters中匹配的documents元素 { $set: { 'clients.$.documents.$$doc.doc_upload': '新的上传路径' } }, { new: true, // 定义数组过滤器:匹配指定_id的documents元素 arrayFilters: [ { '$$doc._id': ObjectId("637c648fb8fcfb2bc3071bbe") } ] } ); res.status(200).json(updatedUser); } catch (err) { res.status(500).json(err); } } else { res.status(401).json('You can update only your account.'); } })
场景2:根据document的name更新
如果需要根据document的name字段匹配(比如更新name为Acte de mariage的元素),修改arrayFilters即可:
arrayFilters: [ { '$$doc.name': 'Acte de mariage' } ]
关键说明
clients.$中的$会匹配外层clients数组中client_Username为elsa的元素arrayFilters里的$$doc是自定义的占位符,代表documents数组中符合过滤条件的元素- 确保MongoDB版本支持arrayFilters(3.6及以上版本已支持)
内容的提问来源于stack exchange,提问作者Vaodi
相关产品推荐
相关产品推荐

