首页 > 解决方案 > MongoDb C# 驱动程序 - DeleteMany 不适用于 In Filter

问题描述

我尝试使用 MongoDb C# Driver 删除重复记录。下面的脚本既不会引发错误,也不会删除任何记录。有什么建议吗?

[BsonIgnoreExtraElements]
public class ApiUsers
{
    [BsonId]
    [BsonRepresentation(BsonType.String)]
    public ObjectId Id { get; set; }
    
    public string UserEMail { get; set; }
}

var users = _mongoDbContext.ApiUsers.Find(f => f.UserEMail == email).ToList();
var oneUser = users[0];

var idsToDelete = users.Where(x => !x.Id.Equals(oneUser.Id)).Select(x => x.Id);
if (idsToDelete.Any())
{   //Delete Dublicates
    
    var idsToDeleteFilter = Builders<ApiUsers>.Filter.In(t => t.Id, idsToDelete);
    var result = _mongoDbContext.ApiUsers.DeleteMany(idsToDeleteFilter);
} 

我也尝试过像下面这样的 DeleteOne 方法,但它也不起作用,

foreach (var idToDelete in idsToDelete)                        
   _mongoDbContext.ApiChildUsers.DeleteOne(Builders<ApiChildUsers>.Filter.Eq(u => u.Id, idToDelete)); 

标签: c#mongodbmongodb-.net-driverasp.net-core-2.1

解决方案


您可以尝试以下方法,您可以返回一个 Id 以保留并删除其余部分,如下所示:

var filter = Builders<ApiUsers>.Filter.Where(u => u.UserEMail == "test@test.com");
var projection = Builders<ApiUsers>.Projection.Expression(u=>u.Id);
var options = new FindOptions<ApiUsers, string> { Projection = projection, Limit = 1 };

var idToKeep = collection.FindSync(filter, options).ToList()[0];

collection.DeleteMany(
    u => u.UserEMail == "test@test.com" &&
         u.Id != idToKeep);

作为旁注,我建议您将 ID 存储在服务器中ObjectId而不是字符串,因为它的效率较低,因为 ObjectId 只需要 12 个字节来存储,这将小于它的十六进制字符串表示形式。

这是一个使用 mongodb.entities 的不太冗长的测试程序:

using MongoDB.Entities;
using System.Threading.Tasks;

namespace TestApp
{
    public class ApiUsers : Entity
    {
        public string UserEMail { get; set; }
    }

    internal static class Program
    {
        private static async Task Main()
        {
            await DB.InitAsync("test", "localhost");

            await new[] {
                new ApiUsers { UserEMail = "test@test.com"},
                new ApiUsers { UserEMail = "test@test.com"},
                new ApiUsers { UserEMail = "test@test.com"},
                new ApiUsers { UserEMail = "teX@teX.com"},
            }.SaveAsync();

            var idToKeep = (await DB.Find<ApiUsers, string>()
                                    .Match(u => u.UserEMail == "test@test.com")
                                    .Project(u => u.ID)
                                    .Limit(1)
                                    .ExecuteAsync())[0];

            await DB.DeleteAsync<ApiUsers>(
                u => u.UserEMail == "test@test.com" &&
                     u.ID != idToKeep);
        }
    }
}


推荐阅读