Драйвер С# mongodb 2.0 - Как выполнить массовую операцию?

Я перешел с 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);

Эта работа продолжается, задумана, или я что-то упускаю? Спасибо.


person Adrian Lopez    schedule 28.02.2016    source источник


Ответы (3)


Установите для свойства IsUpsert объекта UpdateOneModel значение true, чтобы превратить обновление в опрокинуть.

var upsertOne = new UpdateOneModel<BsonDocument>(filter, update) { IsUpsert = true };
bulkOps.Add(upsertOne);
collection.BulkWrite(bulkOps);
person JohnnyHK    schedule 28.02.2016
comment
Это следует добавить в документацию. Спасибо!! - person Adrian Lopez; 29.02.2016
comment
что такое массопс? Как мне его получить? - person gyozo kudor; 09.11.2017
comment
@gyozokudor bulkOps List<WriteModel<T>> - person Mathias; 12.04.2018
comment
Что я должен поместить в переменные filterи update? - person gsubiran; 24.04.2019

данная коллекция монго

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);
person Aviko    schedule 21.03.2018
comment
Мне нравится этот подход, но правда ли, что каждая запись в записях должна содержать значение _Id? В источнике моих записей нет поля _Id. Поэтому мне нужно найти отдельные записи, используя альтернативный уникальный ключ, например. укей. Когда я использовал x.ukey == record.ukey, обновление не удалось, потому что поле record._Id содержит все нули. Есть ли хороший способ сделать это за один upsert или мне нужно получить целевые записи, чтобы я мог установить столбец _Id перед выполнением upsert? - person BigTFromAZ; 04.05.2018
comment
Я не решался использовать после того, как увидел «Заменить». Поэтому использовал UpdateOneModel, это было слишком медленно. Только что пришел еще раз и проверил это бум! Это так быстро. - person vinoth kumar; 15.06.2020

Вот метод расширения, основанный на ответе @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);

    }
person Abba    schedule 07.01.2020