How to not delete items in document when using $set with $arrayToObject?

Hi,

I’m working on a project where users need to be able to update and add contact information. Users can add as many means of contact or social media information as they want. I have a schema that looks like:

const ContactInfo = new mongoose.Schema({
      number: Number,
      email: String,
      facebook: String,
      snapchat: String,
      twitter: String,
      instagram: String,
      ...
})

const UsersSchema = new mongoose.Schema({
     name: String,
     contactInfo:  ContactInfo
})

I want to be able to send to the backend only the contactInfo data that the user provides, so I’m trying to do that using $arrayToObject. The problem that I’m having is that when I using this with $set its deleting/ ignoring the previously saved data. Here is an example of the issue: mongoplayground. I would really appreciate any help or advice on how to fix this. Thank you!

Hey, welcome to the MongoDB community.

See if this helps you =D

db.collection.update({
  "_id": "63492520b5ef3f0bf00282ca"
},
{
  $set: {
    "contactInfo.email": "instagram",
    "contactInfo.example_gmail_com": "@example"
  }
},
{
  upsert: true
})

Output:

[
  {
    "_id": "63492520b5ef3f0bf00282ca",
    "contactInfo": {
      "email": "instagram",
      "example_gmail_com": "@example",
      "number": "xxx-xxx-xxxx"
    }
  }
]

I think we are missing some facts about your use-case.

Why do you use $arrayToObject? How is your array of k/v values built?

I think that sharing the code around your update could lead to more specif recommendation. The reason why the other fields are removed from contactInfo is that you $set the top field contactInfo. Basically, you request to change the object contactInfo with the result of $arrayToObject. Using the dot notation as shown by Samuel_84194 is the way to set sub-fields inside an object without losing the other sub-fields.

If you have no choice and you receive the array as you shared then you would need to use reduce on this array to convert it to the dot notation.