5

Hello I have this document

{
  email: "email@gmail.com",
  list: [
    {
      "product": "Car",
      "price": 18
    },
    {
      "product": "Boat",
      "price": 20 
    }
  ]
}

I am wondering how to identify the document using the email parameter and update a specific object in the list parameter by finding the product with the "Car" parameter and updating the price to 15 using the MongoDB Java Driver.

Thank you

prasad_
  • 12,755
  • 2
  • 24
  • 36
jaffer_syed
  • 141
  • 1
  • 3
  • 7
  • what do you mean by "identify the document using the email parameter"?. It would be better if you add some explanation about your problem and code you have tried – deadshot May 15 '20 at 23:14
  • @komatiraju032 I am not sure how to approach this using the MongoDB Driver and the email key in the JSON object that I have provided – jaffer_syed May 15 '20 at 23:18
  • specific object means is there any condition? – deadshot May 15 '20 at 23:20

1 Answers1

8

There are two ways to update the nested document of an array field based upon a condition.

(1) Update using the Positional $ Operator:

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;i.e., "list.product": "Car". And, secondly only the first matching array element will be updated.

db.collection.updateOne( 
  { email: "email@gmail.com", "list.product": "Car" }, 
  { $set: { "list.$.price": 15 } } 
)

(2) Update using the Filtered Positional $[identifier] Operator:

The filtered positional operator $[identifier] identifies the array elements that match the arrayFilters conditions for an update operation.

Note the condition on the array field is not required when using the $[identifier] update operator. And, secondly all the matching array elements ("product": "Car") will be updated.

db.collection.updateOne( 
  { email: "email@gmail.com" }, 
  { $set: { "list.$[ele].price": 15 } },
  { arrayFilters: [ { "ele.product": "Car" } ] }
)


Update using MongoDB Java Driver:

Case 1:

Bson filter = and(eq("email", "email@gmail.com"), eq("list.product", "Car"));
Bson update = set("list.$.price", 15);
UpdateResult result = coll.updateOne(filter, update);

Case 2:

Bson filter = eq("email", "email@gmail.com");
UpdateOptions options = new UpdateOptions()
                              .arrayFilters(asList(eq("ele.product", "Car")));
Bson update = set("list.$[ele].price", 15);
UpdateResult result = coll.updateOne(filter, update, options);

Reference: MongoDB Java Driver

Community
  • 1
  • 1
prasad_
  • 12,755
  • 2
  • 24
  • 36
  • To complete this great anwser, if you don't want to filter the elements in there array (aka if you want to update all the entries of the array), you should use `Updates.set("list.$[].fieldToSet", newValue)` – Eria Apr 14 '22 at 15:13
  • Can you please also tell us how to replace any single object entirely from the list in the example above? Like in your answer you are using $set to update only price of an element in the array of lists. What if we need to replace this object ```{ "product": "Car", "price": 18 },``` entirely with new one? – jarvo69 Dec 14 '22 at 09:43
  • @jarvo69 You can update more than one field using the `$set` update operator. – prasad_ Dec 14 '22 at 10:42