猫鼬查找和更新删除其他字段

时间:2020-09-25 07:28:57

标签: mongodb mongoose

我有这样的架构:

this.schema = new Schema({
    userEmail: String
    environments: [
        {
            envId: String,
            appPreference: String,
            language: String,
            timeZone: String,
            summaryNotificationSchedule: {
                timeOfTheDay: String
            }
        }
    ]
});

更新请求:

{
  "envId": "u2",
  "appPreference": "put2",
  "timeZone": "gmt",
  "summaryNotificationSchedule.timeOfTheDay": "32400",
}

如您所见,我没有在更新请求中发送 "language": "abc",,结果我看到language字段已删除。我想更新字段,但不删除其他字段

猫鼬查找和更新呼叫:

await this.model.findOneAndUpdate({ userEmail, 'environments.envId': envId }, { $set: { 'environments.$': setPreferenceFields } }, { new: true });

2 个答案:

答案 0 :(得分:2)

您可以先根据请求创建更新对象:

let request = {
  "envId": "u2",
  "appPreference": "put2",
  "timeZone": "gmt",
  "summaryNotificationSchedule.timeOfTheDay": "32400",
};

let update = Object.keys(request).reduce((acc, cur) => {
  acc[`environments.$.${cur}`] = request[cur];
  return acc;
}, {})

console.log(update);

然后将其传递给更新:

await this.model.findOneAndUpdate({ userEmail, 'environments.envId': envId }, { $set: update }, { new: true });

答案 1 :(得分:1)

您必须使用数组的父键名称指定属性,就像这样,

await this.model.findOneAndUpdate(
    { 
        userEmail, 
        'environments.envId': envId
    }, 
    { 
        $set: { 
            'environments.$.envId': "u2", 
            'environments.$.appPreference': "put2",
            'environments.$.timeZone': "gmt",
            'environments.$.summaryNotificationSchedule.timeOfTheDay': "32400"
        } 
    }, 
    { new: true }
)

另一个选择update with aggregation pipeline从MongoDB v4.2开始,这个过程比上面的方法要花点时间,

  • $map迭代environments数组循环
  • $cond检查条件,如果envId等于匹配的envId,然后使用$mergeObjects合并对象更新对象和当前对象,否则返回当前对象
await this.model.findOneAndUpdate(
    { userEmail },
    [
        {
            $set: {
                environments: {
                    $map: {
                        input: "$environments",
                        in: {
                            $cond: [
                                {$eq: ["$$this.envId", envId]}, // add update id
                                {
                                    $mergeObjects: [
                                        "$$this",
                                        setPreferenceFields  // your update fields
                                    ]
                                },
                                "$$this"
                            ]
                        }
                    }
                }
            }
        }
    ],
    {new: true}
)