Note:Please use mongodb shell to execute the codes.
Let's say i have one student document as below
{
"_id" : 4,
"grades" : [
{
"grade" : 80,
"mean" : 75,
"std" : 8
},
{
"grade" : 85,
"mean" : 90,
"std" : 5
},
{
"grade" : 85,
"mean" : 90,
"std" : 5
},
{
"grade" : 85,
"mean" : 95,
"std" : 6
},
{
"grade" : 90,
"mean" : 85,
"std" : 5
}
]
}
We have 2 problems :
Problem 1 : lets say you wants to updates all subdocuments with _id=4 && grades.grade = 85 && grades.std = 5, with std=6 you will write as follows
db.students.update( {'$and':[ { _id: 4},{ "grades.grade": 85 }, {"grades.std": 5 } ]}, { $set: { "grades.$.std" : 6 } } );
Now if you execute above statement multiple times(3 times) then ideally it should update 2nd,3rd sub-documents
But last sub-document is also getting updated beacause it has std=5 match, but we have given condition as $and not $or, then how come last document is getting updated?
Problem 2 : Now let's say you wants to remove the subdocument itself matching with query criteria. I tried following statement
db.students.update({_id:4,'grades.grade':85},{'$unset':{'grades.$':1}})
because $unset will put null in case of sub-documents/arrays, how to solve this problem?
How to replicate in your mongodb console ?
db.students.insert( { "_id" : 4, "grades" : [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 5 }, { grade: 85, mean: 90, std: 5 }, { grade: 85, mean: 95, std: 6 }, { grade: 90, mean: 85, std: 5 } ] });
To update, use update () along with $set. Let us create a collection with documents − Display all documents from a collection with the help of find () method − > db.demo134.update( ...
The update method is used to modify specific fields in the whole document within the collection of MongoDB. The deleteOne method is used to delete a particular document within the MongoDB collection. Here, we have learned how we can update single or multiple documents upon particular criteria.
When the db.collection.update () performs update operations (and not document replacement operations), db.collection.update () can target multiple shards. Starting in MongoDB 4.2, replace document operations attempt to target a single shard, first by using the query filter.
When we execute these queries in the MongoDB Shell, it returned the following message in the shell as you can observe in the below image. The returned message of Shell is not more communicating but when you execute the same command on Robo 3T it will show you a message as how many rows get updated in the update query execution.
The '$' operator only updates the first match so given:
db.students.insert({ "_id" : 4, "grades" : [
{ grade: 80, mean: 75, std: 8 },
{ grade: 85, mean: 90, std: 5 },
{ grade: 85, mean: 90, std: 5 },
{ grade: 85, mean: 95, std: 6 },
{ grade: 90, mean: 85, std: 5 } ]});
To update you need to target with $elemMatch
like so:
db.students.update( { _id: 4, "grades": {$elemMatch: {"grade": 85, "std": 5 }}},
{ $set: { "grades.$.std" : 6 } });
However, you have two grades that match {"grades.grade": 85, "grades.std": 5}
and $
only updates the first so you need to loop until all updated:
db.students.update( { _id: 4, "grades": {$elemMatch: {"grade": 85, "std": 5 }}},
{ $set: { "grades.$.std" : 6 } })
while (db.getLastErrorObj()['n'] > 0) {
db.students.update( { _id: 4, "grades": {$elemMatch: {"grade": 85, "std": 5 }}},
{ $set: { "grades.$.std" : 6 } })
}
Problem 2: Same thing applies - you need to loop to $pull
matching elements:
db.students.update({_id:4,'grades': {$elemMatch: {'grade':85}}}, {'$pull': {'grades': {'grade':85}}})
You need to use $elemMatch to match inside an array. The query rules in MongoDB specify that for conditions on array elements, any array element where any of the conditions matches is considered a match. With $elemMatch
, all conditions need to match on the same element.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With