В прошлой теме разбиралась фильтрация с помощью определения объекта BsonDocument. Другим способом для создания фильтрации представляет применение класса FilterDefinitionBuilder - построителя фильтров. Он подразумевает подразуемвает применения одного или нескольких методов фильтрации:
// определяем построитель фильтров var builder = Builders<BsonDocument>.Filter; // создаем фильтр, который выбирает все документы, где Name = "Tom" var filter = builder.Eq("Name", "Tom");
Так, в данном случае применяется метод Eq(). Он возвращает фильтр, который выбирает все документы, где поле Name равно "Tom".
FilterDefinitionBuilder определяет богатую палитру методов, которые могут применяться для построения фильтра.
Eq: выбирает только те документы, у которых значение определенного поля равно некоторому значению
Ne: выбирает только те документы, у которых значение определенного поля не равно некоторому значению
Gt: выбирает только те документы, у которых значение определенного поля больше некоторого значения
Gte: выбирает только те документы, у которых значение определенного поля больше или равно некоторому значению
Lt: выбирает только те документы, у которых значение определенного поля меньше некоторого значения
Lte: выбирает только те документы, у которых значение определенного поля меньше или равно некоторому значению
In: получает все документы, у которых значение поля может принимать одно из указанных значений
Nin: противоположность оператору In
- выбирает все документы, у которых значение поля не принимает одно из
указанных значений
{ "_id" : ObjectId("63596dc76348749cac779373"), "Name" : "Tom", "Age" : 38, "Languages" : ["english", "german", "spanish"] } { "_id" : ObjectId("63596dc76348749cac779374"), "Name" : "Bob", "Age" : 42, "Languages" : ["english"] } { "_id" : ObjectId("63596dc76348749cac779375"), "Name" : "Sam", "Age" : 25, "Languages" : ["english", "spanish"] } { "_id" : ObjectId("63596dc76348749cac779376"), "Name" : "Alice", "Age" : 33 } { "_id" : ObjectId("63596dc76348749cac779377"), "Name" : "Tom", "Age" : 33, "Languages" : ["english"] }
Выберем все документы, где поле "Name" равно "Tom":
using MongoDB.Bson; using MongoDB.Driver; MongoClient client = new MongoClient("mongodb://localhost:27017"); var db = client.GetDatabase("test"); var collection = db.GetCollection<BsonDocument>("users"); // определяем построитель фильтров var builder = Builders<BsonDocument>.Filter; // определяем фильтр - находим все документы, где Name = "Tom" var filter = builder.Eq("Name", "Tom"); var users = await collection.Find(filter).ToListAsync(); foreach (var user in users) { Console.WriteLine(user); }
Здесь в качестве фильтра передается объект new BsonDocument { { "Name", "Tom" } }
, то есть мы выбираем все документы, в которых Name="Tom". В итоге мы получим следующий вывод:
{ "_id" : ObjectId("63596dc76348749cac779373"), "Name" : "Tom", "Age" : 38, "Languages" : ["english", "german", "spanish"] } { "_id" : ObjectId("63596dc76348749cac779377"), "Name" : "Tom", "Age" : 33, "Languages" : ["english"] }
Аналогично можно использовать и другие методы. Например, фильтр для поиска документов, где поле "Age" больше или равно 33:
var filter = builder.Gte("Age", 33);
Методы In и Nin позволяют проверить на соответствие одному из значений некоторого диапазона. Например, найдем документы, где Age равен 33 или 25:
var filter = builder.In("Age", new int[] { 33, 25 });
В примере выше мы получаем из коллекции объекты BsonDocument, поэтому построитель фильтров FilterDefinitionBuilder также типизируется классом BsonDocument. Если же мы получаем коллекцию объектов другого класса, например, класса Person, то и FilterDefinitionBuilder также типизируется этим классом:
using MongoDB.Bson; using MongoDB.Driver; MongoClient client = new MongoClient("mongodb://localhost:27017"); var db = client.GetDatabase("test"); var collection = db.GetCollection<Person>("users"); var builder = Builders<Person>.Filter; var filter = builder.Eq("Name", "Tom"); var users = await collection.Find(filter).ToListAsync(); foreach (var user in users) { Console.WriteLine(user.Name); } class Person { public ObjectId Id { get; set; } public string Name { get; set; } = ""; public int Age { get; set; } public List<string>? Languages { get; set; } }
С помощью стандартных операций программирования конъюнкции, дизъюнкции и логического отрицания, а также соответствующих им методов можно комбинировать запросы:
Операция ! и метод Not возвращают документы, которые НЕ соответствуют определенному условию.
Операция | и метод Or возвращают документы, которые соответствуют как минимум одному из фильтров из набор.
Операция & и метод And возвращают документы, которые соответствуют всем фильтрам из набора
Или, например, зададим фильтр для выбора документов, у которых поле "Age" имеет значение от 33 и выше, либо поле "Name" имеет значение "Tom":
using MongoDB.Bson; using MongoDB.Driver; MongoClient client = new MongoClient("mongodb://localhost:27017"); var db = client.GetDatabase("test"); var collection = db.GetCollection<BsonDocument>("users"); var builder = Builders<BsonDocument>.Filter; var filter = builder.Or(builder.Eq("Name", "Tom"), builder.Gte("Age", 33)); var users = await collection.Find(filter).ToListAsync(); foreach (var user in users) { Console.WriteLine(user); }
Здесь применяется метод Or()
. Он выбирает документы, которые соответствуют одному из подфильтров, которые передаются в метод в качестве параметров. Так, в данном
случае передаем два фильтра: builder.Eq("Name", "Tom")
и builder.Gte("Age", 33)
. D получим следующий результат:
{ "_id" : ObjectId("63596dc76348749cac779373"), "Name" : "Tom", "Age" : 38, "Languages" : ["english", "german", "spanish"] } { "_id" : ObjectId("63596dc76348749cac779374"), "Name" : "Bob", "Age" : 42, "Languages" : ["english"] } { "_id" : ObjectId("63596dc76348749cac779376"), "Name" : "Alice", "Age" : 33 } { "_id" : ObjectId("63596dc76348749cac779377"), "Name" : "Tom", "Age" : 33, "Languages" : ["english"] }
Определение фильтра можно сократить, использовав вместо метода Or операцию |:
var filter = builder.Eq("Name", "Tom") | builder.Gte("Age", 33);
Метод And()
, напротив, выбирает документы, которые соответствуют всем подфильтрам. Например,
выберем документы, где одновременно поле "Age" имеет значение от 33 и выше и поле "Name" имеет значение "Tom":
var filter = builder.And(builder.Eq("Name", "Tom"), builder.Gte("Age", 33));
Консольный вывод для данного фильтра:
{ "_id" : ObjectId("63596dc76348749cac779373"), "Name" : "Tom", "Age" : 38, "Languages" : ["english", "german", "spanish"] } { "_id" : ObjectId("63596dc76348749cac779377"), "Name" : "Tom", "Age" : 33, "Languages" : ["english"] }
Вместо метода And можно использовать операцию &
:
var filter = builder.Eq("Name", "Tom") & builder.Gte("Age", 33);
Операция ! и метод Not позволяют инвертировать условие. Например, найдем документы, одновременно поле "Age" меньше 33 и поле "Name" не равно "Tom":
var filter = !(builder.Eq("Name", "Tom") | builder.Gte("Age", 33)); // альтернативный вариант var filter2 = builder.Not(builder.Or(builder.Eq("Name", "Tom"), builder.Gte("Age", 33)));
Exists: выбирает из бд те документы, в которых присутствует определенное поле
NotExists: выбирает из бд те документы, в которых отсутствует определенное поле
Например, фильтр для выбора документов, где присутствует поле "Languages":
var builder = Builders.Filter; var filter = builder.Exists("Languages");
Regex в качестве параметра получает имя поля и регулярное выражение, которому должно соответствовать значение этого поля. Например, найдем все документы, где поле Name заканчивается на букву "m":
var builder = Builders.Filter; var filter = builder.Regex("Name", new BsonRegularExpression("m$"));
Для определения регулярного выражения применяется класс BsonRegularExpression, в конструктор которого передается сообтвенно регулярное выражение.
Метод Where()
принимает условие, которому должны соответствовать документы. Например, выберем все документы, где поле "Age" имеет значение меньше 30:
using MongoDB.Bson; using MongoDB.Driver; MongoClient client = new MongoClient("mongodb://localhost:27017"); var db = client.GetDatabase("test"); var collection = db.GetCollection<BsonDocument>("users"); var builder = Builders<BsonDocument>.Filter; var filter = builder.Where(d=>d["Age"]<30); var users = await collection.Find(filter).ToListAsync(); foreach (var user in users) { Console.WriteLine(user); }
В данном случае фильтр типизируется типом BsonDocument:
var builder = Builders<BsonDocument>.Filter;
Поэтому метод Where в качестве параметра получает делегат - некоторое действие, которое принимает объект BsonDocument и возвращает true (если этот документ соответствует условию) или false (если не соответствует)
var filter = builder.Where(d=>d["Age"]<30);
Данный метод удобен, когда фильтр и коллекция тизируются стандартными классами C#, которые описывают данные:
using MongoDB.Bson; using MongoDB.Driver; MongoClient client = new MongoClient("mongodb://localhost:27017"); var db = client.GetDatabase("test"); var collection = db.GetCollection<Person>("users"); var builder = Builders<Person>.Filter; var filter = builder.Where(p=>p.Age<30); var users = await collection.Find(filter).ToListAsync(); foreach (var user in users) { Console.WriteLine($"{user.Name} - {user.Age}"); } class Person { public ObjectId Id { get; set; } public string Name { get; set; } = ""; public int Age { get; set; } }
All: выбирает все документы, в которые содержат все элементы массива
Size: выбирает все документы, которые содержат определенное число элементов
Например, найдем все документы, где в массиве Languages есть значения "english" и "spanish":
var builder = Builders.Filter; var filter = builder.All("Languages", new string[] { "english", "spanish" }); var users = await collection.Find(filter).ToListAsync(); foreach (var user in users) { Console.WriteLine(user); }
Консольный вывод:
{ "_id" : ObjectId("63596dc76348749cac779373"), "Name" : "Tom", "Age" : 38, "Languages" : ["english", "german", "spanish"] } { "_id" : ObjectId("63596dc76348749cac779375"), "Name" : "Sam", "Age" : 25, "Languages" : ["english", "spanish"] }
Или найдем документы, где в массиве Languages только 1 элемент:
var builder = Builders.Filter; var filter = builder.Size("Languages", 1);