admin管理员组

文章数量:1355529

I inserted a client in my "clients" collection.

data inserted

{
    "type": "private",
    "name": "Client 1",
    "contact": {
        "email": "[email protected]",
        "phone": {
            "dialCode": "242",
            "number": "066788998"
        },
        "location": {
            "address": "69 Fake Avenue",
            "city": "Fake City",
            "country": "Fake country",
            "state": null
        }
    }
}

Now I want to update client's email.

With my API, i submit this data to update client's email.

{
   "contact": {
        "email":null
    }
}

mongodb/mongoose is updating contact but phone and location are removed. Why ?

This is how i update my data await Client.findByIdAndUpdate(id, {$set: data}}).

How to only update email without removing other data ? How to update a nested object

I inserted a client in my "clients" collection.

data inserted

{
    "type": "private",
    "name": "Client 1",
    "contact": {
        "email": "[email protected]",
        "phone": {
            "dialCode": "242",
            "number": "066788998"
        },
        "location": {
            "address": "69 Fake Avenue",
            "city": "Fake City",
            "country": "Fake country",
            "state": null
        }
    }
}

Now I want to update client's email.

With my API, i submit this data to update client's email.

{
   "contact": {
        "email":null
    }
}

mongodb/mongoose is updating contact but phone and location are removed. Why ?

This is how i update my data await Client.findByIdAndUpdate(id, {$set: data}}).

How to only update email without removing other data ? How to update a nested object

Share Improve this question asked Mar 29 at 16:29 Steeven DelucisSteeven Delucis 3625 silver badges19 bronze badges 3
  • 1 since you "set" the contacts part of your document with the api data which has only the email it replaces the contents .ideally $set: { "contact.email": null } should only update the email. but if you need to be more dynamic you might have to transform your api data before feeding into the query – cmgchess Commented Mar 29 at 16:38
  • dot annotation ? If i have 10 data to update, how i'm supposed to deal with ? – Steeven Delucis Commented Mar 29 at 17:26
  • 2 This is a common problem when you have an API that selectively updates only part of a document. It has with a fairly reliable solution using dot-object to prepare your update object before passing to mongoose like in this example. – jQueeny Commented Mar 29 at 17:36
Add a comment  | 

2 Answers 2

Reset to default 1

I don't think there is a generic solution to handle all sorts of payload. But for your current use case of updating contact.email, you can use $mergeObjects in an update with aggregation pipeline.

db.collection.update({
  "_id": 1
},
[
  {
    "$set": {
      "contact": {
        "$let": {
          "vars": {
            "payload": {
              "contact": {
                "email": null
              }
            }
          },
          "in": {
            "$mergeObjects": [
              "$contact",
              "$$payload.contact"
            ]
          }
        }
      }
    }
  }
])

Mongo Playground

Instead of replacing the entire contact object, update only the email field using MongoDB's dot notation as contact.email

await Client.findByIdAndUpdate(
    id,
    { $set: { "contact.email": <New_Email> } }, 
    { new: true, runValidators: true } 
);

returns updated doc & enforce schema validation

本文标签: nodejsMongoose update nested data without erase other dataStack Overflow