我有一个MongoDB,我在其中记录带有SubItem数组的Items。在添加或更新SubItem时,我首先Find
主Item
,然后我将新的SubItem
添加到SubItems
数组中,并替换整个Item
。在我开始批量插入SubItems
之前,这很有效。
我认为我的问题是查找和更新不是一个原子操作,结果是我丢失了SubItems
。
我正在使用.NET MongoDB.Driver,我的save方法如下所示:
public Task Save(string itemId, SubItem subItem)
{
var itemFilter = Builders<Item>.Filter.Eq(v => v.Id, itemId);
var collection = _db.GetCollection<Item>("Items");
var item = await collection.Find(itemFilter).SingleOrDefaultAsync();
item.SubItems.Add(subItem);
collection.ReplaceOneAsync(itemFilter, item, new UpdateOptions() { IsUpsert = true }).Wait();
return Task.FromResult(0);
}
这是我的数据模型:
public class Item
{
public string Id { get; set; }
public List<SubItem> SubItems { get; set; }
}
public class SubItem
{
public string Id { get; set; }
}
有没有办法在一个操作中插入或更新SubItem
,这样即使我有多个进程试图同时更新文档,我也可以确保整个Item
文档保持一致?
答案 0 :(得分:2)
您是否查看了AddToSet方法,如果将此与更新函数结合使用而不是替换它,则应该更好地控制原子性。
var updateBuilder = Builders<Item>.Update.AddToSet(items => items.SubItems, new SubItem());
collection.UpdateOne(itemFilter, updateBuilder);
就像你的情况一样。
public Task Save(string itemId, SubItem subItem)
{
var itemFilter = Builders<Item>.Filter.Eq(v => v.Id, itemId);
var collection = _db.GetCollection<Item>("Items");
var updateBuilder = Builders<Item>.Update.AddToSet(items => items.SubItems, subItem);
collection.UpdateOneAsync(itemFilter, updateBuilder, new UpdateOptions() { IsUpsert = true }).Wait();
}