首页 > 解决方案 > 使用 mongoose 仅​​更新嵌套 json 文档中的一个元素

问题描述

当嵌套 json 元素时,如何使用 Mongoose 只更新文档中的一个部分?

我想更新一个文档,只需将“darkMode”从 false 设置为 true,而不需要 GETing 和 PUTing 整个“settins”部分。猫鼬可以做到这一点吗?

        "settings": {
            "darkMode": false,
            "tipOfTheDay": true,
            "paperFormat": "DINA4",
        },

如果我放这个,我将丢失文档“设置”部分中的所有内容:

        "settings": {
            "darkMode": true,
        },

我的 NodeJS 后端看起来像这样。我目前正在使用 findByIdAndUpdate 。也许有更好的方法?

exports.updateProfile = async (req, res, next) => {
    const profile = await Profile.findByIdAndUpdate(req.params.id, req.body, {
        new: true,
        runValidators: true
    });

    if (!profile) {
        return res.status(400).json({success: false});
    }

    res.status(200).json({success: true, data: profile});
}

标签: node.jsmongodbmongoose

解决方案


为了更新嵌入文档中的字段,您必须使用 a$set运算符(因为您的文档是一个对象,我们正在处理对象中的一个对象)

从 mongodb 文档:

https://docs.mongodb.com/v2.4/reference/method/db.collection.update/#update-specific-fields-in-embedded-documents

更新嵌入文档中的特定字段 使用点符号更新嵌入文档中的值。

所以对你来说,如果我们假设这里的 req.body{ darkMode: true }

    const profile = await Profile.findByIdAndUpdate(
     req.params.id, 
     { $set: { 'settings.darkMode': req.body.darkMode } }, 
     {
        new: true,
        runValidators: true
    });

但这完全取决于您如何从客户端发送数据,如果您发送一个仅包含修改字段的对象,那么您必须专门 $set 它们以保持其他值不变,如上所示。要自动执行此操作,您还可以使用花哨的循环构建查询:

let query = { $set: {} }

Object.keys(req.body).forEach(requestBodyKey => {
    let requestBodyFieldValue = req.body[requestBodyKey];
    query.$set[`settings.${requestBodyKey}`] = requestBodyFieldValue;
})

或者您可以首先查询您的文档以获取 current_settings,然后使用 javascript 您将合并两个对象(例如,{...myCurrentSettings, ...myNewerSettings } 参见扩展运算符Object.assign()),然后对其进行更新以确保您保留以前的、未触及的字段值。


推荐阅读