FilterDefinitionBuilder и определение фильтров

Последнее обновление: 27.10.2022

В прошлой теме разбиралась фильтрация с помощью определения объекта 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

Regex в качестве параметра получает имя поля и регулярное выражение, которому должно соответствовать значение этого поля. Например, найдем все документы, где поле Name заканчивается на букву "m":

var builder = Builders.Filter;
var filter = builder.Regex("Name", new BsonRegularExpression("m$"));

Для определения регулярного выражения применяется класс BsonRegularExpression, в конструктор которого передается сообтвенно регулярное выражение.

Метод Where

Метод 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); 
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850