我开始在工作中使用MongoDB (With spring-data-mongo),所以一切都好。但我想知道MongoDB如何处理发生的更新?更具体地说,处理这些问题的最佳实践是什么?
例如,我有一个包含Map
的Document@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
问题是myMap中会有什么?是B还是A加的分录?还是两者都有?
可以对update()
或findAndUpdate()
使用$push
数组更新操作符。
假设一个像
这样的对象{ name : "test", myMap : {
"1" : { list : [1,2,3] },
"2" : { list : [4,5,6] }
}}
你可以直接执行
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]}
这将把值附加到现有的条目数组中,或者创建一个新的条目(使用一个新的数组)。
From the docs:
$push操作符将指定的值追加到数组中。
如果该字段在要更新的文档中不存在,$push将以该值作为数组字段的元素。
为了完成,您应该查看其他更新操作符的文档,如$set
, $inc
, $max
等。
如果你只是使用
update(..., { name : "test", myMap : {
"1" : { list : [1,2,3] },
...
})
在两个线程中,结果不会被指定,而是取决于最后执行哪个更新请求。