How to write a mongoose update to update a whole document, various subdocuments included

Viewed 93

I'm trying to write a way to update a whole MongoDB document including subdocuments using Mongoose and a supplied update object. I want to supply an object from my client in the shape of the schema and then iterate over it to update each property in the document including those in nested subdocuments in arrays.

So if my schema looked like this:

const Person = new Schema({
  name: String,
  age: Number,
  addresses: [
    {
      label: String,
      fullAddress: String,
    },
  ],
  bodyMeasurements: {
    height: Number,
    weight: Number,
    clothingSizes: {
      jacket: Number,
      pants: Number
    },
  },
})

I would want to supply an object to update an existing document that looked something like this:

{
  "_id": "217a7f84685f49642635dff0",
  "name": "Dan",
  "addresses": [
    {
      "_id": "5f49647f84f02635df217a68",
      "label": "Home 2"
    },
    {
      "label": "Work",
      "fullAddress": "6 Elm Street"
    }
  ],
  "bodyMeasurements": {
    "_id": "2635df217a685f49647f84f0",
    "weight": 90,
    "clothingSizes": {
      "_id": "217a685f4962635df49647f84f0",
      "pants": 32
    }
  }
}

The code would need to iterate through all the keys and values of the object entries, and where it found a Mongo ID it would know to update that specific item (like the "Home 2" address label), and where it didn't it would know to add it (like the second "Work" address here), or replace it if it was a property on the top level. (like the "name" property with "Dan")

For a one dimensional Schema without taking into account _id's this would work:

for (const [key, value] of Object.entries(req.body)) {
    person[key] = value;
}

But not for any nested subdocuments or documents in arrays. I don't want to have to specify the name of the subdocuments for each case. I am trying to find a way to update any Schema's documents and subdocuments generically.

I imagine there might be some recursion and the Mongoose .set() method needed to handle deeply nested documents.

0 Answers
Related