使用 MongoDB C# 驱动程序连接两个集合的查询中的 NOT IN 过滤器

NOT IN filter in a query with a join of two collections using MongDB C# driver

我有两个可以用这些 classes(简化版)建模的集合:

public class Profile
{
    [BsonId]
    [BsonRepresentation(BsonType.String)]
    public Guid? Id { get; set; }
    public string Name { get; set; }        
    [BsonRepresentation(BsonType.String)]
    public Guid UserId { get; set; }
}

public class User
{
    [BsonId]
    [BsonRepresentation(BsonType.String)]
    public Guid? Id { get; set; }
    public string UserName { get; set; }        
    public bool IsConfirmed { get; set; }        
}

我需要一个查询来获取所有 UserIsConfirmed 标志等于 true 的 UserProfiles,然后我需要过滤掉 ID 包含在 a 中的那些排除的 ID 列表:

IList<Guid> profileIdsToExclude

这是我到目前为止构建的查询:

var professionalProfilesQuery = 
    (from profileCollection in _mongoContext.Database.GetCollection<Profile>("profiles").AsQueryable()
     join userCollection in _mongoContext.Database.GetCollection<User>("users").AsQueryable()
     on profileCollection.UserId equals userCollection.Id.Value
     into users
     orderby profileCollection.Name
     select new ProfessionalProfile
     {
         Id = profileCollection.Id,
         Name = profileCollection.Name,                                                 
         UserId = profileCollection.UserId,
         IsConfirmed = users.First().IsConfirmed,                                                 
     })
     .Where(p => p.IsConfirmed && !profileIdsToExclude.Contains(p.Id.Value));

其中ProfessionalProfile是一个class到return的查询结果:

public class ProfessionalProfile
{
    public Guid? Id { get; set; }
    public string Name { get; set; }        
    public Guid UserId { get; set; }
    public bool IsConfirmed { get; set; }        
}

我得到了 UserProfiles,只有 IsConfirmed 等于 true 的。但是那些 ID 在被排除的 ID 列表中的那些不会被过滤掉,而是被查询return编辑。

知道我想做的事情是否可行以及如何实现吗?

提前致谢。

你这里的问题是由于类型混淆引起的。

驱动程序创建的查询在末尾包含一个 $match 阶段,看起来有点像这样:

{
    $match: {
        IsConfirmed: true,
        Id: {
            $nin: [ BinData(3, "DBA38D51FC28094BA2D6439E95643A49") ]
        }
    }
}

所以它实际上是在尝试排除具有特定 Guid 值的字段的结果。但是,您正在为您的 Guid 存储字符串,因此过滤器不会排除任何内容。为了解决这个问题,您可以这样做:

改变

.Where(p => p.IsConfirmed && !profileIdsToExclude.Contains(p.Id.Value));

进入

.Where(p => p.IsConfirmed && !profileIdsToExclude.Contains(p.Id));

IList<Guid> profileIdsToExclude

进入

IList<Guid?> profileIdsToExclude