C# mongodb驱动程序2.0 - 如何在批量操作中进行upsert?

27
我从1.9迁移到2.2,阅读文档后发现在批量操作期间无法执行upsert,因为操作不允许选项。
bulkOps.Add(new UpdateOneModel<BsonDocument>(filter, update));
collection.BulkWrite(bulkOps);

应该是这样的

options.isUpsert = true;
bulkOps.Add(new UpdateOneModel<BsonDocument>(filter, update, options));
collection.BulkWrite(bulkOps);

这是正在进行中的工作、有意为之,还是我遗漏了什么?谢谢。

3个回答

36

UpdateOneModelIsUpsert属性设置为true,即可将更新操作转换为upsert。

var bulkOps = new List<WriteModel<BsonDocument>>();
// Create and add one or more write models to list
var upsertOne = new UpdateOneModel<BsonDocument>(filter, update) { IsUpsert = true };
bulkOps.Add(upsertOne);
// Write all changes as a batch
collection.BulkWrite(bulkOps);

这应该被添加到文档中。谢谢! - Adrian Lopez
1
什么是bulkOps?我该如何获取它? - gyozo kudor
4
bulkOps 是一个 List<WriteModel<T>>,我的翻译没有改变原意,且尽可能地通俗易懂。 - Mathias
4
我该在 filterupdate 变量中放什么内容? - gsubiran
1
当您的ID是一个字符串时,这并不起作用。 - irperez

34

给定MongoDB集合

IMongoCollection<T> collection

需要插入的记录的可枚举对象,其中T具有Id字段。

IEnumerable<T> records 

以下代码片段将进行批量更新(根据实际情况,筛选条件可能会有所更改):

var bulkOps = new List<WriteModel<T>>();
foreach (var record in records)
{
    var upsertOne = new ReplaceOneModel<T>(
        Builders<T>.Filter.Where(x => x.Id == record.Id),
        record)
    { IsUpsert = true };
    bulkOps.Add(upsertOne);
}
collection.BulkWrite(bulkOps);

1
我喜欢这种方法,但是“records”中的每个“record”都必须包含一个_Id值,这是真的吗?我的记录来源不包括_Id字段。因此,我需要使用替代唯一键(例如ukey)来定位单个记录。当我使用x.ukey == record.ukey时,更新失败,因为record._Id字段全部为零。有没有一种好的方法可以在一个upsert中完成这个操作,或者我必须获取目标记录,以便在执行upsert之前设置_Id列? - BigTFromAZ
我在看到 Replace 后犹豫了一下,所以使用了 UpdateOneModel,但它太慢了。现在再来检查,哇!它非常快。 - vinoth kumar

1
这里是一个基于 @Aviko 的扩展方法。
public static BulkWriteResult<T> BulkUpsert<T>(this IMongoCollection<T> collection, IEnumerable<T> records)
    {
        string keyname = "_id";

        #region Get Primary Key Name 
        PropertyInfo[] props = typeof(T).GetProperties();

        foreach (PropertyInfo prop in props)
        {
            object[] attrs = prop.GetCustomAttributes(true);
            foreach (object attr in attrs)
            {
                BsonIdAttribute authAttr = attr as BsonIdAttribute;
                if (authAttr != null)
                {
                    keyname = prop.Name;
                }
            }
        }
        #endregion

        var bulkOps = new List<WriteModel<T>>();


        foreach (var entry in records)
        {
            var filter = Builders<T>.Filter.Eq(keyname, entry.GetType().GetProperty(keyname).GetValue(entry, null));

            var upsertOne = new ReplaceOneModel<T>(filter, entry){ IsUpsert = true };

            bulkOps.Add(upsertOne);
        }

        return collection.BulkWrite(bulkOps);

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接