C
C#3y ago
ampere

.NET MongoDB Driver - Unsupported Filter Contains

So here's my method in my repository layer... which basically checks: if there were existing questions (it's an interview app for company recruiters) delete only those whose Practice property is equal to ANY of the ones that came in the request payload.
public async Task<Unit> Handle(Query request, CancellationToken cancellationToken)
{
// Save current questions
var currentQuestions = (await mongoDatabaseInstance.FindAllAsync<Question>("questions", cancellationToken)).ToList();
var modified = false;

try
{
if (currentQuestions.Any())
{
// We create a filter to only delete questions that are going to be replaced, based on 'Practice'
// e.g. if we are uploading a spreadsheet that only contains a JAVA sheet, delete all questions where Practice is JAVA
Expression<Func<Question, bool>> filter = x => request.Questions.Select(x => x.Practice).Contains(x.Practice);

// Delete all questions and attempt to import new ones
await mongoDatabaseInstance.DeleteMany("questions", filter, cancellationToken);
}

modified = true;
await mongoDatabaseInstance.InsertMany("questions", request.Questions, cancellationToken);
return Unit.Value;
}
catch (Exception ex)
{
// Restore previous questions if there were any and new questions got rejected
if (currentQuestions.Any() && modified)
{
await mongoDatabaseInstance.InsertMany("questions", currentQuestions, cancellationToken);
}

throw new Exception($"Error trying to insert questions, file probably doesn't comply with the format.", ex);
}
}
public async Task<Unit> Handle(Query request, CancellationToken cancellationToken)
{
// Save current questions
var currentQuestions = (await mongoDatabaseInstance.FindAllAsync<Question>("questions", cancellationToken)).ToList();
var modified = false;

try
{
if (currentQuestions.Any())
{
// We create a filter to only delete questions that are going to be replaced, based on 'Practice'
// e.g. if we are uploading a spreadsheet that only contains a JAVA sheet, delete all questions where Practice is JAVA
Expression<Func<Question, bool>> filter = x => request.Questions.Select(x => x.Practice).Contains(x.Practice);

// Delete all questions and attempt to import new ones
await mongoDatabaseInstance.DeleteMany("questions", filter, cancellationToken);
}

modified = true;
await mongoDatabaseInstance.InsertMany("questions", request.Questions, cancellationToken);
return Unit.Value;
}
catch (Exception ex)
{
// Restore previous questions if there were any and new questions got rejected
if (currentQuestions.Any() && modified)
{
await mongoDatabaseInstance.InsertMany("questions", currentQuestions, cancellationToken);
}

throw new Exception($"Error trying to insert questions, file probably doesn't comply with the format.", ex);
}
}
The method DeleteMany calls this function:
await MongoDatabase.GetCollection<TDocument>(collectionName).DeleteManyAsync(filter, cancellationToken)
await MongoDatabase.GetCollection<TDocument>(collectionName).DeleteManyAsync(filter, cancellationToken)
Which calls this function from the MongoDB Driver (seems to be version 2.17.1.0):
public virtual Task<DeleteResult> DeleteManyAsync(FilterDefinition<TDocument> filter, CancellationToken cancellationToken = default(CancellationToken))
{
return DeleteManyAsync(filter, null, cancellationToken);
}
public virtual Task<DeleteResult> DeleteManyAsync(FilterDefinition<TDocument> filter, CancellationToken cancellationToken = default(CancellationToken))
{
return DeleteManyAsync(filter, null, cancellationToken);
}
The problem is that I'm getting an exception related to the use of .Contains in my filter. Why is this? How would I rewrite the filter expression to avoid using it and achieve the same results?
1 Reply
ampere
ampereOP3y ago
Solved, I had to modify the DeleteMany method implementation to receive a FilterDefinition<TDocument> instead of an Expression<Func<TDocument, bool>>, so I could formulate and pass the following filter:
var practicesToDelete = request.Questions.Select(x => x.Practices).Distinct();
var filter = Builders<Question>.Filter.In(x => x.Practice, practicesToDelete);
var practicesToDelete = request.Questions.Select(x => x.Practices).Distinct();
var filter = Builders<Question>.Filter.In(x => x.Practice, practicesToDelete);
Want results from more Discord servers?
Add your server