Reputation: 2877
I migrated from 1.9 to 2.2 and reading the documentation I was surprised to discover that is not possible to upsert during a bulk operation anymore, since operations don't allow options.
bulkOps.Add(new UpdateOneModel<BsonDocument>(filter, update));
collection.BulkWrite(bulkOps);
Should be
options.isUpsert = true;
bulkOps.Add(new UpdateOneModel<BsonDocument>(filter, update, options));
collection.BulkWrite(bulkOps);
Is this work in progress, intended, or I'm missing something? Thank you.
Upvotes: 29
Views: 22984
Reputation: 311905
Set the IsUpsert
property of the UpdateOneModel
to true to turn the update into an 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);
Upvotes: 39
Reputation: 549
Here is an extension method based on @Aviko response
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);
}
Upvotes: 1
Reputation: 1199
given mongo collection
IMongoCollection<T> collection
and enumerable of records to insert where T has Id field.
IEnumerable<T> records
this snippet will do a bulk upsert (the filter condition may be changed according to the situation):
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);
Upvotes: 38