I’m trying to delete the subobject ‘apples’ from my documents and update the ‘fruitInventory’ property, decrease by the amount of apples.
I’m confused on how to proceed, should I use dot notation or do a full text search for apples? I don’t know if this matters but you can assume apples will always be in field 1.
// Document 1
{
"1": {
"apples": 3,
"fruitInventory": 21,
"oranges": 12,
"kiwis": 3,
"lemons": 3
},
"2": {
"bananas": 4,
"fruitInventory": 12,
"oranges": 8,
},
"_id": "1"
}
// Document 2
{
"1": {
"apples": 5,
"fruitInventory": 10,
"oranges": 2,
"pears": 3
},
"2": {
"bananas": 4,
"fruitInventory": 6,
"cherries": 2,
},
"_id": "2"
}
Result should be like this:
// Document 1
{
"1": {
"fruitInventory": 18,
"oranges": 12,
"kiwis": 3,
"lemons": "3"
},
"2": {
"bananas": 4,
"fruitInventory": 12,
"oranges": 8,
},
"_id": "1"
}
// Document 2
{
"1": {
"fruitInventory": 5,
"oranges": "2",
"pears": "3"
},
"2": {
"bananas": 4,
"fruitInventory": 6,
"cherries": 2,
},
"_id": "2"
}
Thanks in advance for your help.
In the MongoDB query language there is no way to update a document using information from the document. In other words, there is no way to increment one property with a value from another property. To be specific: there is no way to increment the
fruitInventoryby X where X is the value of theapplesproperty as an atomic operation.The way I would implement this, while avoiding races, is with two
findAndModifyoperations (seen here in Mongo shell syntax):What happens is this: first I find a document which is not locked (more on this later), and has an
1.applesproperty. The document is returned and updated to get alockedproperty as a single atomic operation. Since the document now has alockedproperty it will not be found by the same query, so this query can be run multiple times in parallel without any risk of modifying the same document twice.I then extract the
1.fruitInventoryand1.apples, to simplify the next expression.The second
findAndModifyupdates the1.fruitInventoryproperty with the new sum, and unsets the1.applesproperty, as well as thelockedproperty (to return the document to its previous, unlocked, state).To update all documents you will have to run this code over and over again until the first
findAndModifyreturnsnull(meaning there are no documents matching the query).