0

I have a mongodb collection Users that looks like this:

{
    "_id" : ObjectId("5dba8987b4a39c13bc104a23"),
    "contact" : {
        "firstName" : "Mark",
        "lastName" : "Doe",
        "parentsBloodType" : [ 
            {
                "type" : "AB+",
            }, 
            {
                "type" : "A+",
            }, 
        ],
    },
    "createdAt" : ISODate("2019-10-31T07:13:11.278Z"),
    "updatedAt" : ISODate("2019-11-26T09:59:41.611Z")
}

I need to run a raw query to update from AB+ to O-. I would also like to check if they match before updating.

I tried this but it added an extra field to the User:

  db.getCollection('users').update(
    {"_id": ObjectId("5dba8987b4a39c13bc104a23")},
    {"$set" : { 'parentsBloodType.' + '0' + '. type' : "O-"}}
    )
2
  • 1
    What happens if both parents have AB+? Do you like to update both or just one? Commented Dec 18, 2019 at 8:22
  • Thanks for pointing it out, I would like to update both. Commented Dec 18, 2019 at 8:35

2 Answers 2

2

This one would do the update:

db.users.update(
   { "_id": ObjectId("5dba8987b4a39c13bc104a23") },
   { "$set": { 'contact.parentsBloodType.0.type' : "O-"} }
)

You an check match with this:

db.users.update(
   {
      "_id": ObjectId("5dba8987b4a39c13bc104a23"),
      "contact.parentsBloodType.type": "AB+"
   },
   { "$set": { 'contact.parentsBloodType.0.type': "AB+" } }
)

This updates the document only if type AB+ exist (at any parent).

Or if you like to check whether the first type is AB+ then use

db.users.update(
   {
      "_id": ObjectId("5dba8987b4a39c13bc104a23"),
      "contact.parentsBloodType.0.type": "AB+"
   },
   { "$set": { 'contact.parentsBloodType.0.type': "AB+" } }
)

However, I assume you are actually looking for this:

db.users.update(
   { "_id": ObjectId("5dba8987b4a39c13bc104a23") },
   { "$set": { 'contact.parentsBloodType.$[p].type': "0-" } },
   { arrayFilters: [{ "p.type": "AB+" }] }
)

Which will update any AB+ to 0- no matter on which position it appears in the array.

Sign up to request clarification or add additional context in comments.

Comments

0

You could use the positional $ operator to update the first element that matches the query document:

db.getCollection('users').update(
  { "_id": ObjectId("5dba8987b4a39c13bc104a23"), "parentsBloodType.type": "AB+" },
  { "$set" : { 'parentsBloodType.$.type' : "O-" } }
)

note that:

  • the positional $ operator acts as a placeholder for the first element that matches the query document, and
  • the array field must appear as part of the query document.

Or use the filtered positional operator $[] if you want to update all elements that match an array filter condition or conditions:

db.students.update(
   { "_id": ObjectId("5dba8987b4a39c13bc104a23") },
   { $set: { "parentsBloodType.$[element].type" : "O-" } },
   { 
     arrayFilters: [ { "element.type": "AB+" } ]
   }
)

1 Comment

Just a note, multi: true means update multiple documents - not update multiple values of an array. I.e. regardless of multi: true or multi: false it will update all matching values in the array. Acctually when you filter on primary key _id: ObjectId(...) then multi: true is pointless.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.