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

meteor, mongodb

Solution

You can update an existing array element using a `$set` operation that uses the `$` positional operator to identify the array element matched in the selector like this:

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

This will replace the matched `schema` element with the one included in the `$set` object.

If you only want to update individual fields of the targeted `schema` element, you can use dot notation. For example, to only update the `size` and `name` fields:

Documents.update(
  {_id: Session.get("current_document_id"), 'schema.name': "first_name"}, 
  {$set: {'schema.$.size': 7, 'schema.$.name': name}}
);

Problem

``` 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"} ```

Original source