如何在C#Mongodb强类型驱动程序中基于嵌套数组元素进行过滤 [英] How to filter based on nested array element in C# Mongodb strongly typed driver

查看:50
本文介绍了如何在C#Mongodb强类型驱动程序中基于嵌套数组元素进行过滤的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using the official C# MongoDb strongly typed driver version 2.7.0-beta001 to interact with MongoDB v 4.0-rc1 on Windows 10 machine.

请考虑以下课程:

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

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

How to update a library document if all author books are verified, here is my code:

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:不支持的过滤器:全部

The last line throws System.ArgumentException: Unsupported filter: All

推荐答案

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

In your POCO class Books is a .NET List so you can (theoretically) use all extension methods (like All). The problem is that it's not LINQ to objects so this expression is not evaluated in memory. MongoDB driver is trying to convert this into MongoDB query and as you can see there's no corresponding operator in MongoDB query language.

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

What you can do ? You can try to rewrite this filter into something else (keeping the same logical meaning). For instance you can use $elemMatch. Instead of trying to find all books with IsVerified equal to true, you can build your query trying to find documents having at least one book equal to false and then use $not to negate that condition. In that case $elemMatch becames helpful:

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

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

因此,至少一个上的表示没有.

然后您的代码应如下所示:

Then your code can look like this:

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#Mongodb强类型驱动程序中基于嵌套数组元素进行过滤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆