4
votes

I'm using mongoose findOneAndUpdate() In mongodb i have a database with objects inside an array look like this:

patients model

{
        "_id" : ObjectId("5cb939a3ba1d7d693846136c"),
        "myArray" : [
            {
                "name" : "PW6178281935-20190425",
                "treatment" : "beauty",
                "value" : 0 <- i want to update this
            },
            {
                "name" : "PW6178281935-24142444",
                "treatment" : "muscle",
                "value" : 0
            }
        ] 
},
 {
        "_id" : ObjectId("5cc123a3bb2d3123a932475f"),
        "myArray" : [
            {
                "name" : "PW6178281935-43535555",
                "treatment" : "helps",
                "value" : 0 
            },
            {
                "name" : "PW6178281935-92732978",
                "treatment" : "documents",
                "value" : 0
            }
        ] 
}

i want to update value of an object with treatment = "beauty" of _id = "5cb939a3ba1d7d693846136c"

in schema "value" has default value of 0

i had tried with this but the value doesn't get update

patients.findOneAndUpdate({$and:[{'patients._id' : 5cb939a3ba1d7d693846136c}, {'myArray.treatment' : beauty}]}, { $set: { 'myArray.$.value': 424214 } }, { new: true });

Am I doing something wrong?

EDIT:

The answer from Frank Rose was right , the reason arrayFilters doesn't work for me because the project i was working on using mongoose 4.4 which doesn't support arrayFilters of mongoDB yet.If you want to use arrayFilters with your project please use mongoose version 5 or later.After i upgrade to mongoose 5.5 i was able to edit the object

2

2 Answers

13
votes

The reason why your query isn't working as expected is because you are not actually targeting the specific array element you want to update.

Here's how I would write the query:

 patients.findOneAndUpdate(
  {_id: "5cb939a3ba1d7d693846136c"},
  {$set: {"myArray.$[el].value": 424214 } },
  { 
    arrayFilters: [{ "el.treatment": "beauty" }],
    new: true
  }
)

To break down what's happening:

1) First we're looking for the patient by ID

2) Then using $set we specify which updates are being applied. notice the $[el] syntax. this is referring to an individual element in the array. you can name it what ever you want but it must match the variable name used in arrayFilters.

3) Then in the configuration object we specify arrayFilters which is saying to only target array elements with "treatment" equal to "beauty"

Note though that it will target and update all array elements with treatment equal to "beauty". If you haven't already you'll want to ensure that the treatment value is unique. $addToSet could be useful here, and would be used when adding elements to the array.

1
votes

Ok i found out and managed to update but the right answer from Frank Rose is better cause it worked in my other projects but not the current one

Because i was using version 4.4 of mongoose, only version 5 and above can use arrayfilter

For mongoose version < 5:

patients.findOneAndUpdate(
  {
    _id: "5cb939a3ba1d7d693846136c",
    'images.treatment': "beauty"
  },
  {$set: {"myArray.$.value": 424214 } },
  { 
    new: true
  }
)