Reputation: 14769
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"}
Upvotes: 10
Views: 16824
Reputation: 39
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 } } ]
}
)
Upvotes: 2
Reputation: 311875
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}}
);
Upvotes: 22