Как фильтровать на основе вложенного элемента массива в C # Mongodb строго типизированный драйвер - PullRequest
0 голосов
/ 06 июня 2018

Я использую официальный строго типизированный драйвер C # MongoDb версии 2.7.0-beta001 для взаимодействия с MongoDB v 4.0-rc1 на компьютере с Windows 10.

Рассмотрим следующие классы:

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: Неподдерживаемый фильтр: Все

1 Ответ

0 голосов
/ 07 июня 2018

В вашем классе POCO Books - это список .NET, поэтому вы можете (теоретически) использовать все методы расширения (например, All).Проблема в том, что это не LINQ для объектов, поэтому это выражение не оценивается в памяти.Драйвер MongoDB пытается преобразовать это в запрос MongoDB, и, как вы можете видеть, в языке запросов MongoDB нет соответствующего оператора.

Что вы можете сделать?Вы можете попробовать переписать этот фильтр во что-то другое (сохранив то же логическое значение).Например, вы можете использовать $ elemMatch .Вместо того, чтобы пытаться найти все книги с IsVerified, равным true, вы можете создать свой запрос, пытаясь найти документы, имеющие хотя бы одну книгу, равную false, и затем использовать $not, чтобы отменить это условие.В этом случае $elemMatch становится полезным:

Оператор $ elemMatch сопоставляет документы, содержащие поле массива, с хотя бы одним элементом , который соответствует всем указанным критериям запроса.

То есть не на хотя бы на одном означает нет .

Тогда ваш код может выглядеть следующим образом:

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...