在 MongoDB 中安全地插入或更新子文档
Safely insert or update subdocument in MongoDB
我有一个 MongoDB 用于记录带有子项数组的项。添加或更新 SubItems 时,我首先 Find
主 Item
,然后我将新的 SubItem
添加到 SubItems
的数组中并替换整个 Item
。在我开始批量插入 SubItems
之前,这一直有效 "great"。
我认为我的问题是查找和更新不是一个原子操作,结果是我输了 SubItems
。
我正在使用 .NET MongoDB.Driver,我的保存方法如下所示:
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
文档的一致性同一时间?
您是否看过 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();
}
我有一个 MongoDB 用于记录带有子项数组的项。添加或更新 SubItems 时,我首先 Find
主 Item
,然后我将新的 SubItem
添加到 SubItems
的数组中并替换整个 Item
。在我开始批量插入 SubItems
之前,这一直有效 "great"。
我认为我的问题是查找和更新不是一个原子操作,结果是我输了 SubItems
。
我正在使用 .NET MongoDB.Driver,我的保存方法如下所示:
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
文档的一致性同一时间?
您是否看过 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();
}