【问题标题】:Safely insert or update subdocument in MongoDB在 MongoDB 中安全地插入或更新子文档
【发布时间】:2017-09-17 22:29:40
【问题描述】:

我有一个 MongoDB,我在其中记录带有子项数组的项。添加或更新子项时,我先FindItem,然后将新的SubItem添加到SubItems的数组中,并替换整个Item。在我开始批量插入 SubItems 之前,这工作“很棒”。

我认为我的问题是查找和更新不是一个原子操作,结果是我失去了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“在某种程度上”简化情况,“如果”数组内容只是值或“单个”属性。但是,如果有多个属性,“唯一性”是指在该上下文中这些属性的组合,它会退回到“测试”方法。
  • “upsert”问题是当任何此类更新需要“测试”数组中元素的存在时,“any”否定结果意味着“upsert”总是在您的实际意图可能已经发生时发生“追加”现有文档的数组而不是新文档。因此,您采用的实际过程实际上取决于您的预期模式。如果您真的想要“upserts”并且想要数组中的多个属性,那么您实际上的意思是要执行“多个操作”。

标签: c# mongodb atomic


【解决方案1】:

您是否看过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如何“知道”如何更新正确的子项?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-07
  • 2018-04-05
  • 2014-09-08
  • 2015-08-15
  • 2012-09-16
  • 2019-12-02
  • 1970-01-01
相关资源
最近更新 更多