Skip to content

Commit

Permalink
Merge pull request #77 from Etherna/fix/MODM-170-upsert-invalidate-cache
Browse files Browse the repository at this point in the history
fix and refactor upsert
  • Loading branch information
tmm360 authored Aug 25, 2024
2 parents b21f3f1 + 3246c10 commit 13b23d8
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 15 deletions.
6 changes: 3 additions & 3 deletions src/MongODM.Core/Repositories/IRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ Task ReplaceAsync(
/// <param name="cancellationToken">The cancellation token</param>
/// <typeparam name="TItem">Item type</typeparam>
/// <returns>The model as result from find before update</returns>
Task<TModel> UpsertAddToSetAsync<TItem>(
Task<TModel?> UpsertAddToSetAsync<TItem>(
Expression<Func<TModel, bool>> filter,
Expression<Func<TModel, IEnumerable<TItem>>> setField,
TItem itemValue,
Expand All @@ -191,9 +191,9 @@ Task<TModel> UpsertAddToSetAsync<TItem>(
/// <param name="cancellationToken">The cancellation token</param>
/// <typeparam name="TItem">Item type</typeparam>
/// <returns>The model as result from find before update</returns>
Task<TModel> UpsertAddToSetAsync<TItem>(
Task<TModel?> UpsertAddToSetAsync<TItem>(
FilterDefinition<TModel> filter,
Expression<Func<TModel, IEnumerable<TItem>>> setField,
FieldDefinition<TModel> setField,
TItem itemValue,
TModel onInsertModel,
CancellationToken cancellationToken = default);
Expand Down
29 changes: 17 additions & 12 deletions src/MongODM.Core/Repositories/Repository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -397,30 +397,29 @@ public virtual Task ReplaceAsync(
}
}

public Task<TModel> UpsertAddToSetAsync<TItem>(
public Task<TModel?> UpsertAddToSetAsync<TItem>(
Expression<Func<TModel, bool>> filter,
Expression<Func<TModel, IEnumerable<TItem>>> setField,
TItem itemValue,
TModel onInsertModel,
CancellationToken cancellationToken = default) =>
UpsertAddToSetAsync(
new ExpressionFilterDefinition<TModel>(filter),
setField,
new ExpressionFieldDefinition<TModel>(setField),
itemValue,
onInsertModel,
cancellationToken);

public Task<TModel> UpsertAddToSetAsync<TItem>(
public Task<TModel?> UpsertAddToSetAsync<TItem>(
FilterDefinition<TModel> filter,
Expression<Func<TModel, IEnumerable<TItem>>> setField,
FieldDefinition<TModel> setField,
TItem itemValue,
TModel onInsertModel,
CancellationToken cancellationToken = default) =>
AccessToCollectionAsync(collection =>
AccessToCollectionAsync(async collection =>
{
var modelMap = DbContext.MapRegistry.GetModelMap(typeof(TModel));
var fieldDefinition = new ExpressionFieldDefinition<TModel>(setField);
var fieldRendered = fieldDefinition.Render((IBsonSerializer<TModel>)modelMap.ActiveSerializer, DbContext.SerializerRegistry);
var fieldRendered = setField.Render((IBsonSerializer<TModel>)modelMap.ActiveSerializer, DbContext.SerializerRegistry);

// Serialize model.
var modelBsonDoc = new BsonDocument();
Expand All @@ -435,17 +434,23 @@ public Task<TModel> UpsertAddToSetAsync<TItem>(

// Update "update" definition with OnInsert instructions.
var onInsertUpdate = modelBsonDoc[0].AsBsonDocument.Elements
.Where(element => element.Name != modelMap.ActiveSchema.IdMemberMap!.BsonMemberMap.ElementName &&
element.Name != fieldRendered.FieldName.Split('.').First())
.Where(element => element.Name != modelMap.ActiveSchema.IdMemberMap!.BsonMemberMap.ElementName && //exclude ID
element.Name != fieldRendered.FieldName.Split('.').First()) //and the field itself
.Select(element => Builders<TModel>.Update.SetOnInsert(element.Name, element.Value));
var upsertUpdate = Builders<TModel>.Update.Combine(onInsertUpdate.Append(
Builders<TModel>.Update.AddToSet(fieldDefinition, itemValue)));
Builders<TModel>.Update.AddToSet(setField, itemValue)));

// Exec on db.
return collection.FindOneAndUpdateAsync(filter, upsertUpdate, new FindOneAndUpdateOptions<TModel>()
var oldDocument = await collection.FindOneAndUpdateAsync(filter, upsertUpdate, new FindOneAndUpdateOptions<TModel>()
{
IsUpsert = true,
}, cancellationToken);
}, cancellationToken).ConfigureAwait(false);

// Remove old document from cache, if present.
if (oldDocument is not null)
DbContext.DbCache.RemoveModel(oldDocument.Id!);

return oldDocument;
});

// Protected virtual methods.
Expand Down

0 comments on commit 13b23d8

Please sign in to comment.