Danny
Danny

Reputation: 179

How to fix DeleteManyAsync returning 0 records deleted with Filter?

I have a delete method that takes in an IEnumerable of Ids that are of type string, and have a filter taking in those ids using Filter.In. However when passing in a set of ids I am getting a count of 0 for records deleted. Is my filter causing the issue?

I've created a test method to test my delete method and am passing in ids to try and have them deleted.


Test Solution

MongodDB Test method for delete method

    [Theory]
    [InlineData(1)]
    [InlineData(100)]
    public async void TEST_DELETE(int quantity)
    {
        using (var server = StartServer())
        {
            // Arrange
            var collection = SetupCollection(server.Database, quantity);
            var dataUtility = new MongoDataUtility(server.Database, 
    MongoDbSettings);
            var service = new MongoDatabaseService(dataUtility, Logger);

            var items = 
    collection.FindSync(FilterDefinition<BsonDocument>.Empty)
    .ToIdCollection();
            _output.WriteLine(JsonConvert.SerializeObject(items, 
    Formatting.Indented));

            // Act
            var result = await 
    dataUtility.DeleteIdentifiedDataAsync(items, CollectionName);
            _output.WriteLine(JsonConvert.SerializeObject(result, 
    Formatting.Indented));

            // Assert
            Assert.True(result.DeletedCount.Equals(items.Count));
        }
    }

Setup collection

    public IMongoCollection<BsonDocument> SetupCollection(IMongoDatabase db, 
    int quantity)
    {
        var collection = db.GetCollection<BsonDocument>(CollectionName);

        AddCreateDateIndex(collection);
        SeedData(collection, quantity);

        return collection;
    }

Seed data

    public void SeedData(IMongoCollection<BsonDocument> collection, int? 
    quantity = null)
    {
        if (quantity != null && quantity > 0)
        {
            collection.InsertMany(GenerateTestData((int)quantity));
        }
    }

Project

MongoDB delete method

 public async Task<DeleteResult> 
 DeleteIdentifiedDataAsync(IEnumerable<ObjectId> ids, string Resource, 
 CancellationToken cancellationToken = default)
    {
        var collection = _db.GetCollection<BsonDocument>(Resource);
        var filter = Builders<BsonDocument>.Filter.In("_id", ids);

        if (ids != null && ids.Any() )
        {
            return await collection.DeleteManyAsync(filter, 
 cancellationToken);
        }

        return null;
    }

Extensions

    public static ICollection<ObjectId> ToIdCollection(this 
    IAsyncCursor<BsonDocument> @this)
    {
        return @this.Find(Builders<BsonDocument>.Filter.Empty)
            .ToEnumerable()
            .Select(s => s["_id"].AsObjectId)
            .ToList();
    }

Upvotes: 2

Views: 1326

Answers (1)

mickl
mickl

Reputation: 49945

Your ToIdCollection method gets all the ids but also converts them from ObjectId to String when you run .Select(dict => dict["_id"].ToString()). MongoDB compares both values and types when you run DeleteManyAsync and that's why there is no match - you're trying to compare list of strings against ObjectIds that are stored in the database.

To fix that you can replace ToIdCollection with following implementation:

return @this.Find(Builders<BsonDocument>.Filter.Empty)
                        .ToEnumerable()
                        .Select(s => s["_id"].AsObjectId)
                        .ToList()

Upvotes: 1

Related Questions