DEV Community

Mario
Mario

Posted on

Remove and modify nested documents in MongoDB

I have a rather complex Document Structure to fulfill the approach of have all the data available when you execute one query. However there is the big issue of modifying it.

So lets have a look at our Object that we want to modify


{
    "_id" : ObjectId("5b0bf696cb5dd80010bea0a3"),
    "domains" : [ 
        {
            "_id" : ObjectId("5b0bf696cb5dd80010bea0a4"),
            "DKIMRecordName" : "mailjet._domainkey.example.de.",
            "DKIMRecordValue" : "k=rsa; p=000000000000000000000000",
            "DKIMStatus" : "Not Checked",
            "Domain" : "example.de",
            "IsCheckInProgress" : false,
            "SPFRecordValue" : "v=spf1 include:spf.mailjet.com ?all",
            "SPFStatus" : "Not Checked",
            "emails" : [ 
                {
                    "_id" : ObjectId("5b0bf696cb5dd80010bea0a5"),
                    "CreatedAt" : ISODate("2018-05-28T12:31:18.000Z"),
                    "DNSID" : "2837371580",
                    "Email" : "no-reply@example.de",
                    "EmailType" : "unknown",
                    "Filename" : "",
                    "ID" : "216556",
                    "IsDefaultSender" : false,
                    "Name" : "",
                    "Status" : "Inactive"
                },
                {
                    "_id" : ObjectId("5b0bf696cb5dd45410bea0a5"),
                    "CreatedAt" : ISODate("2018-05-28T12:31:18.000Z"),
                    "DNSID" : "2837371580",
                    "Email" : "newsletter@example.de",
                    "EmailType" : "unknown",
                    "Filename" : "",
                    "ID" : "216556",
                    "IsDefaultSender" : false,
                    "Name" : "",
                    "Status" : "Inactive"
                }
            ]
        }
}


Enter fullscreen mode Exit fullscreen mode

So if you want to modify one of them we will use the following

db.yourCollection.update({'domains.emails.Email': 'no-reply@example.de'},
{ $set: {'email.$.emails':  
    {
                    "_id" : ObjectId("5b0bf696cb5dd80010bea0a5"),
                    "CreatedAt" : ISODate("2018-05-28T12:31:18.000Z"),
                    "DNSID" : "2837371580",
                    "Email" : "no-reply@example.de",
                    "EmailType" : "unknown",
                    "Filename" : "",
                    "ID" : "216556",
                    "IsDefaultSender" : false,
                    "Name" : "",
                    "Status" : "Active"
                }

  },
{multi: true})

Enter fullscreen mode Exit fullscreen mode

Why do we have to put in the whole Object? Sadly we can not use a second positional $ operator. So we have to provide the full nested Document. Additional it MUST be included as part of the Query document, otherwise it would not recognize it. This would throw the Error "The positional operator did not find the match needed from the query."

Also what we can do is a pull operation:

db.yourCollection.update({'email.emails.Email': 'no-reply@example.de'},
{ $pull: {'email.$.emails':  {'Email': 'no-reply@example.de'}}  },
{multi: true})
Enter fullscreen mode Exit fullscreen mode

This will remove the Child Document from the nested Array.

Be aware, the multi: true will not work and you have to run the query multiple times.

Top comments (3)

Collapse
 
rkristelijn profile image
Remi Kristelijn • Edited

I don't think you have to put the whole object, you can set individual properties of one of the elements using a double search param and place the '$set' on the field itself:

using your example above, something like:

db.yourCollection.update({
  _id: ObjectId("5b0bf696cb5dd80010bea0a3"),
  'emails._id': ObjectId("5b0bf696cb5dd80010bea0a5")
}, {'$set': {'emails.$.Email': 'w.white@break.bad'}})

Good to read that '$pull' will remove an element, note that '$push' will add an element

Collapse
 
lucasmonstro profile image
Lucas Silva

You mean { $pull: {'domain.$.emails': {'Email': 'no-reply@example.de'}} }?

Collapse
 
ashin2052 profile image
Ashin2052

what is email.emails.Email?