c# - 如何在 C# Mongodb 强类型驱动程序中基于嵌套数组元素进行过滤

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

我正在使用官方 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

最佳答案

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

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

The $elemMatch operator matches documents that contain an array field with at least one element that matches all the specified query criteria.

所以至少一个上意味着没有

那么你的代码可以是这样的:

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

关于c# - 如何在 C# Mongodb 强类型驱动程序中基于嵌套数组元素进行过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50727526/

相关文章:

node.js - 使用 NodeJS 的异步函数填充不起作用

node.js - node+mongo,除非在本地主机上,否则无法插入到 mongo

c# - 速度优化 Windows 窗体应用程序

c# - 在 .NET 中,我什么时候必须引用外部库也引用的 DLL?

c# - .NET 4 中的多线程改进

c# - 如何使用Dockerfile覆盖ASP.NET Core连接字符串

.net - 在已部署的ASP.NET网站项目上,是否可以在不重新编译的情况下更新.resx文件?

带有空更新文档的 MongoDB upsert

c# - 如何启动异步任务对象

c# - 如何在 C# 中将未包含在 datagridview 中的其他数据库值显示到另一个表单中?