mongoose find and update removes the other fields

99封情书 提交于 2021-01-29 09:45:36

问题


I have schema like this:

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

Update request:

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

As you can see, I am not sending "language": "abc", in the update request and in the result I see the language field is removed. I want to update the fields but not remove the other fields

Mongoose find and update call:

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

回答1:


You can create update object from your request first:

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

Then pass it to the update:

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



回答2:


You have to specify property with parent key name of an array, it should be like this way,

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

Another option, update with aggregation pipeline start from MongoDB v4.2, this little lengthy process then above method,

  • $map to iterate loop of environments array
  • $cond check condition if envId is equal to matching envId then merge objects update objects and current objects using $mergeObjects otherwise return current object
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}
)


来源:https://stackoverflow.com/questions/64059736/mongoose-find-and-update-removes-the-other-fields

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!