【问题标题】:How to fix DeleteManyAsync returning 0 records deleted with Filter?如何修复 DeleteManyAsync 返回使用过滤器删除的 0 条记录?
【发布时间】:2019-09-02 06:23:01
【问题描述】:

我有一个删除方法,它接收一个 IEnumerable 的字符串类型的 Id,并有一个过滤器使用 Filter.In 接收这些 id。但是,当传入一组 id 时,删除的记录计数为 0。问题是我的过滤器造成的吗?

我创建了一个测试方法来测试我的删除方法,并传入 id 来尝试删除它们。


测试解决方案

MongodDB 删除方法的测试方法

    [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));
        }
    }

设置集合

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

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

        return collection;
    }

种子数据

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

项目

MongoDB删除方法

 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;
    }

扩展

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

【问题讨论】:

  • 你能同时显示ToIdCollectionSetupCollection吗?你确定查询和删除在同一个数据库/集合上运行吗?
  • @mickl 我添加了与删除方法相关的方法,是的,它们在同一个数据库/集合上运行。

标签: c# mongodb filter ienumerable mongodb-.net-driver


【解决方案1】:

您的ToIdCollection 方法获取所有ids,但在您运行.Select(dict =&gt; dict["_id"].ToString()) 时也将它们从ObjectId 转换为String。当您运行 DeleteManyAsync 时,MongoDB 会比较值和类型,这就是不匹配的原因 - 您尝试将字符串列表与存储在数据库中的 ObjectId 进行比较。

要解决此问题,您可以将 ToIdCollection 替换为以下实现:

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

【讨论】:

  • 通过该实现,我得到严重性代码描述项目文件行抑制状态错误 CS1929 'IAsyncCursor' 不包含'Find' 的定义和最佳扩展方法重载'IMongoCollectionExtensions.Find (IMongoCollection, FilterDefinition, FindOptions)' 需要 'IMongoCollection' 类型的接收器 AHP.DataRetention.Agent C:\Code\Git\ah-platform-dataretention-agent\src\ AHP.DataRetention.Agent\Extensions\MongoExtensions.cs 47 活动
  • @Danny 您需要在几个地方将IEnumerable&lt;string&gt; 更改为IEnumerable&lt;ObjectId&gt;。我已经测试了 var filter = Builders&lt;BsonDocument&gt;.Filter.In("_id", ids); var res = Col.DeleteMany(filter); 传递了 ObjectId 的列表并且它可以工作
  • 我进行了更改和编辑,还阐明了测试解决方案中的内容和项目中的内容。我认为我的主要问题是 IAsyncCursor 没有 find 方法。
  • @Danny 我认为你不需要这部分collection.FindSync(FilterDefinition&lt;BsonDocument&gt;.Empty),你不能在ToIdCollection 中直接在MongoCollection 上运行Find 吗?那应该可以解决问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 2014-06-17
  • 1970-01-01
  • 2012-03-18
  • 2021-12-20
  • 2019-01-07
  • 1970-01-01
相关资源
最近更新 更多