用猫鼬更新嵌套json文档中的一个元素

时间:2020-03-04 21:54:02

标签: node.js mongodb mongoose

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

我想更新一个文档,只是将“ darkMode”从false设置为true,而无需获取和放置整个“ 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});
}

1 个答案:

答案 0 :(得分:1)

要更新嵌入文档中的字段,您必须使用$set运算符(由于您的文档是对象,因此我们正在处理对象中的对象)

从mongodb文档中:

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

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

因此,对于您来说,如果我们假设此处的要求正文为{ 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 } see spread operatorObject.assign()),然后对其进行更新以确保您将保留之前未更改的字段值。