Reputation: 5582
I started using MongoDB (With spring-data-mongo) at work and so fare all good. But I was wondering how does MongoDB deals with occurrent update? And more specifically what are the best practices to handle these ?
For example I have a Document that contains a Map
@Document(collection = "test)
public class Test {
private String name;
private Map<Long, Holder> myMap;
}
public class Holder {
private List<Integer> list;
}
{
"name": "test",
"myMap: "{"1":"{"list":[1,2,3]}", "2":"{"list":[1,2,3]}"}"
}
Thread A: retrieves the Test Document
Thread A: gets myMap and add a new entry in the list for key "1"
Thread B: retrieves the Test Document
Thread B: gets myMap and add a new entry in the list for key "1"
Thread B: saves the Test Document
Thread A: saves the Test Document
The question is what will be in the myMap ? the entry added by B or A ? or both ?
Upvotes: 2
Views: 1204
Reputation: 1557
You can use the $push
array update operator with either update()
or findAndUpdate()
.
Assuming an object like
{ name : "test", myMap : {
"1" : { list : [1,2,3] },
"2" : { list : [4,5,6] }
}}
you can simply do
update(..., { $push:{ "myMap.2.list" : 8 }}) // results in "2" : {list:[4,5,6,8]}
update(..., { $push:{ "myMap.3.list" : 9 }}) // results in new entry "3" : {list:[9]}
This will either append the value to the existing entry array or create a new entry (with a new array).
From the docs:
The $push operator appends a specified value to an array.
If the field is absent in the document to update, $push adds the array field with the value as its element.
For completion, you should check out the docs of other update operators like $set
, $inc
, $max
, etc.
If you simply use
update(..., { name : "test", myMap : {
"1" : { list : [1,2,3] },
...
})
in both threads, the result won't be specified and will depend on which update request gets executed last.
Upvotes: 1