Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update a subdocument contained in an array contained in a MongoDB document

Tags:

mongodb

meteor

Documents.update(
  {_id: Session.get("current_document_id")}, 
  {$push: {schema: {type: "text", size: size, name: name, label: label}}}
);

The above query is a Meteor collection, and 'Documents.update' maps to 'db.documents.update' in MongoDB documentation (http://docs.mongodb.org/manual/applications/update/). With that query I can add a schema document inside the main document. Subdocuments are stored in an array:

Document:
  schema:
    array:
      {type: "text", size: 6, name: "first_name", label: "First name"},
      {type: "text", size: 6, name: "last_name", label: "Last name"}

I want to modify the name and size attributes of the subdocuments with this query:

Documents.update(
  {_id: Session.get("current_document_id"), 'schema' : "first_name"}, 
  {$push: {schema: {type: "text", size: 7, name: name, label: "First Name2"}}}
);

But that operation append a new object directly under schema and deletes the array:

Document:
  schema:
      {type: "text", size: 7, name: "first_name", label: "First Name2"}

How can I modify the query to change the attributes avoiding this issue? After the query I would like to have this document:

Document:
  schema:
    array:
      {type: "text", size: 7, name: "first_name", label: "First name2"},
      {type: "text", size: 6, name: "last_name", label: "Last name"}
like image 435
rtacconi Avatar asked Dec 08 '12 11:12

rtacconi


People also ask

How do you update an element in an array in MongoDB?

You can use the updateOne() or updateMany() methods to add, update, or remove array elements based on the specified criteria. It is recommended to use the updateMany() method to update multiple arrays in a collection.

Can we change _ID in MongoDB?

The _id field is immutable—that is, once a document exists in your MongoDB system, it has, by definition, been assigned an _id, and you cannot change or update its primary key. That said, _id can be overridden when you insert new documents, but by default it will be populated with an ObjectID.


1 Answers

You can use arrayFilters with positional $[] operator

The example below from official mongodb documentation uses "elem" as the positional identifier


Consider a collection students2 with the following documents:

{
   "_id" : 1,
   "grades" : [
      { "grade" : 80, "mean" : 75, "std" : 6 },
      { "grade" : 85, "mean" : 90, "std" : 4 },
      { "grade" : 85, "mean" : 85, "std" : 6 }
   ]
}
{
   "_id" : 2,
   "grades" : [
      { "grade" : 90, "mean" : 75, "std" : 6 },
      { "grade" : 87, "mean" : 90, "std" : 3 },
      { "grade" : 85, "mean" : 85, "std" : 4 }
   ]
}

To modify the value of the mean field for all elements in the grades array where the grade is greater than or equal to 85, use the positional $[] operator and arrayFilters:

db.students2.update(
   { },
   { $set: { "grades.$[elem].mean" : 100 } },
   {
     multi: true,
     arrayFilters: [ { "elem.grade": { $gte: 85 } } ]
   }
)
like image 61
Sri Avatar answered Sep 24 '22 21:09

Sri