1
我有一个MongoDB,在那里我保存了包含子项目数组的项目的记录。当添加或更新子项时,我首先Find
主要Item
,然后我将新的SubItem
添加到SubItems
的数组并替换整个Item
。这工作“很好”,直到我开始批量插入SubItems
。安全地插入或更新MongoDB中的子文档
我想我的问题是,查找和更新不是一个原子操作,结果是我输了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
文档一致,即使我有多个进程试图同时更新文档?
“upserts”和阵列通常不会很好地混合。典型的情况是用多个操作(通常批量)“测试”数组中的项目,然后“推”新项目或“更新”它存在的位置。如果数组内容仅仅是数值或“单个数据”,你可以用['$ addToSet'](https://docs.mongodb.com/manual/reference/operator/update/addToSet/)“稍微” “财产。但是,如果存在多个属性,那么“唯一性”意味着这些属性在这种情况下的组合,并且它返回到“测试”方法。 –
“upsert”问题是,当任何这样的更新需要“测试”数组内存在的元素时,“任何”负面结果意味着当你的实际意图可能是“追加”数组现有文件而不是新文件。所以你使用的实际过程实际上取决于你想要的模式。如果你真的想要“upserts”,并且你想要在数组中有多个属性,那么你实际上是要做“多个操作”。 –