【问题标题】:How to filter based on nested array element in C# Mongodb strongly typed driver如何在 C# Mongodb 强类型驱动程序中基于嵌套数组元素进行过滤
【发布时间】:2018-11-16 13:26:30
【问题描述】:

我正在使用官方 C# MongoDb 强类型驱动程序版本 2.7.0-beta001 在 Windows 10 机器上与 MongoDB v 4.0-rc1 进行交互。

考虑以下类:

public class Library
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }

    public DateTime DateAdded { get; set; }

    public DateTime LastModified { get; set; }

    public string Title { get; set; }

    public Author Author { get; set; }

    public bool AllBooks { get; set; }
}

public class Author {
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string BirthDate { get; set; }

    public string ScientificDegree { get; set; }

    public List<Book> Books { get; set; }
}

public class Book
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }

    public string Title { get; set; }

    public int PublishYear { get; set; }

    public string Content { get; set; }

    public bool IsVerified { get; set; }
}

如果所有作者的书籍都经过验证,如何更新图书馆文档,这是我的代码:

string libraryId = GetLibraryId();

var repository = _database.GetCollection<Library>("Libraries");

var filter = Builders<Library>.Filter.Where(l => l.Id == libraryId &&
                l.Author.Books.All(b => b.IsVerified == true));

var update = Builders<Library>.Update.Set(l => l.AllBooks, true);

await repository.UpdateOneAsync(filter, update);

最后一行抛出 System.ArgumentException: Unsupported filter: All

【问题讨论】:

    标签: c# .net mongodb mongodb-query mongodb-.net-driver


    【解决方案1】:

    在您的 POCO 类中,Books 是一个 .NET 列表,因此您可以(理论上)使用所有扩展方法(如 All)。问题是它不是 LINQ to objects,所以这个表达式不在内存中计算。 MongoDB 驱动程序正在尝试将其转换为 MongoDB 查询,如您所见,MongoDB 查询语言中没有相应的运算符。

    你能做什么?您可以尝试将此过滤器重写为其他内容(保持相同的逻辑含义)。例如,您可以使用$elemMatch。您可以构建查询,尝试查找至少有一本书等于 false 的文档,然后使用 $not 否定该条件,而不是尝试查找所有 IsVerified 等于 true 的书籍。在那种情况下,$elemMatch 变得很有帮助:

    $elemMatch 运算符匹配包含数组字段且至少有一个 元素匹配所有指定查询条件的文档。

    所以至少一个上的not表示

    那么你的代码可以如下所示:

    var col = mydb.GetCollection<Library>("Libraries");
    var filter = Builders<Library>.Filter.Not(
        Builders<Library>.Filter.ElemMatch(x => x.Author.Books, b => b.IsVerified == false));
    
    var update = Builders<Library>.Update.Set(l => l.AllBooks, true);
    
    await col.UpdateManyAsync(filter, update);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-08
      • 2016-11-16
      • 2016-05-10
      • 2022-11-28
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      相关资源
      最近更新 更多