При выборке данных в методы Find()/FindAsync() передается объект BsonDocument, который устанавливает параметры фильтрации. Пустой BsonDocument позволяет выбрать все документы. Но мы можем конкретизировать выборку. Допустим, в коллекции содержатся следующие документы:
{ "_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"); // определяем фильтр - находим все документы, где Name = "Tom" var filter = new BsonDocument { { "Name", "Tom" } }; Listusers = 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"] }
Можно создавать и более сложные критерии фильтрации. Например, найдем все документы, где одновременно и "Name"="Tom", и "Age"=33:
using MongoDB.Bson; using MongoDB.Driver; MongoClient client = new MongoClient("mongodb://localhost:27017"); var db = client.GetDatabase("test"); var collection = db.GetCollection<BsonDocument>("users"); // определяем фильтр - находим все документы, где Name = "Tom" и "Age" = 33 var filter = new BsonDocument { { "Name", "Tom" }, { "Age", 33 } }; Listusers = await collection.Find(filter).ToListAsync(); foreach (var user in users) { Console.WriteLine(user); }
В данном случае BsonDocument-фильтр содержит два элемента:
var filter = new BsonDocument { { "Name", "Tom" }, { "Age", 33 } };
И документы выборки должны соответствовать обоим этим элементам. Так, в данном случае мы получим следующий документ:
{ "_id" : ObjectId("63596dc76348749cac779377"), "Name" : "Tom", "Age" : 33, "Languages" : ["english"] }
Кроме использования свойств мы также можем применять в фильтрах специальные условные операторы. Они задают условие, которому должно соответствовать значение поля документа:
$eq (равно)
$ne (не равно)
$gt (больше чем)
$lt (меньше чем)
$gte (больше или равно)
$lte (меньше или равно)
$in определяет массив значений, одно из которых должно иметь поле документа
$nin определяет массив значений, которые не должно иметь поле документа
Например, найдем все документы, где "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"); // определяем фильтр - находим все документы, где Name != "Tom" var filter = new BsonDocument { { "Name", new BsonDocument("$ne", "Tom") } }; var users = await collection.Find(filter).ToListAsync(); foreach (var user in users) { Console.WriteLine(user); }
Условие задается в виде вложенного документа BsonDocument, где вместо имени элемента применяется условный оператор выборки
var filter = new BsonDocument { { "Name", new BsonDocument("$ne", "Tom") } };
И в данном случае мы получим следующий консольный вывод:
{ "_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 }
Или найдем все документы, где Age больше 33:
var filter = new BsonDocument { { "Age", new BsonDocument("$gt", 33) } }; var users = await collection.Find(filter).ToListAsync();
Или более сложное условие - найдем документы, где Age больше 33 и Name не равно "Tom":
var filter = new BsonDocument { { "Age", new BsonDocument("$gt", 33) }, { "Name", new BsonDocument("$ne", "Tom") } };
Операторы $in и $nin позволяют проверить на соответствие одному из значений некоторого диапазона. Например, найдем документы, где Age равен 33 или 25:
var filter = new BsonDocument { { "Age", new BsonDocument("$in", new BsonArray { 33, 25}) } };
Логические операторы выполняются над условиями выборки:
$or: соединяет два условия, и документ должен соответствовать одному из этих условий
$and: соединяет два условия, и документ должен соответствовать обоим условиям
$not: документ должен НЕ соответствовать условию
$nor: соединяет два условия, и документ должен НЕ соответстовать обоим условиям
Или, например, зададим фильтр для выбора документов, у которых поле "Age" имеет значение от 33 и выше, либо поле "Name" имеет значение "Tom":
var filter = new BsonDocument("$or", new BsonArray{ new BsonDocument("Age",new BsonDocument("$gte", 33)), new BsonDocument("Name", "Tom") }); var users = await collection.Find(filter).ToListAsync();
Здесь применяется оператор $or
. Он выбирает документы, которые соответствуют одному из условий в массиве BsonArray. Так, в данном случае мы получим следующий результат:
{ "_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"] }
Оператор $and
, напротив, выбирает документы, которые соответствуют всем условиям в BsonArray. Например,
выберем документы, где одновременно поле "Age" имеет значение от 33 и выше и поле "Name" имеет значение "Tom":
var filter = new BsonDocument("$and", new BsonArray{ new BsonDocument("Age",new BsonDocument("$gte", 33)), new BsonDocument("Name", "Tom") }); var users = await collection.Find(filter).ToListAsync();
Консольный вывод программы:
{ "_id" : ObjectId("63596dc76348749cac779373"), "Name" : "Tom", "Age" : 38, "Languages" : ["english", "german", "spanish"] } { "_id" : ObjectId("63596dc76348749cac779377"), "Name" : "Tom", "Age" : 33, "Languages" : ["english"] }
Документы могут иметь разный набор полей, что, если нам надо получить те документы, где нет какого-то поля? В этом случае нам надо найти те документы, где данное поле имеет значение BsonNull. Например, найдем документы, где НЕ определен массив Languages:
var filter = new BsonDocument("Languages", BsonNull.Value); // где Languages отсутствует var users = await collection.Find(filter).ToListAsync(); foreach (var user in users) { Console.WriteLine(user); }
Консольный вывод программы:
{ "_id" : ObjectId("63596dc76348749cac779376"), "Name" : "Alice", "Age" : 33 }
Или, наоборот, найдем все документы, где массив Languages определен:
var filter = new BsonDocument("Languages", new BsonDocument { {"$ne", BsonNull.Value } });
Аналогично работает оператор $exists - он позволяет извлечь только те документы, в которых определенное поле присутствует или отсутствует. Например, вернем все документы, в который есть поле Languages:
var filter = new BsonDocument("Languages", new BsonDocument { { "$exists", true } });
Если мы укажем у оператора $exists в качестве параметра false
, то запрос вернет нам только те документы, в которых не определено поле Languages.
var filter = new BsonDocument("Languages", new BsonDocument { { "$exists", false } });
Ряд операторов предназначены для работы с массивами:
$all: определяет набор значений, которые должны иметься в массиве
$size: определяет количество элементов, которые должны быть в массиве
$elemMatch: определяет условие, которым должны соответствовать элементы в массиве
Например, найдем все документы, где в массиве Languages есть значения "english" и "spanish":
var filter = new BsonDocument("Languages", new BsonDocument { {"$all", new BsonArray { "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 filter = new BsonDocument("Languages", new BsonDocument { {"$size", 1 } });
Оператор $regex задает регулярное выражение, которому должно соответствовать значение поля. Например, пусть поле Name заканчивается на букву "m":
var filter = new BsonDocument("Name", new BsonDocument { {"$regex", "m$" } }); 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"] } { "_id" : ObjectId("63596dc76348749cac779377"), "Name" : "Tom", "Age" : 33, "Languages" : ["english"] }
Важно понимать, что $regex принимает не просто строки, а именно регулярные выражения.
Несмотря на то, что в примерах выше мы получали объекты BsonDocument, но точно также можно получать объекты стандартных классов 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"); // определяем фильтр - находим все документы, где Name = "Tom" var users = await collection.Find(new BsonDocument("Name", "Tom")).ToListAsync(); foreach (var user in users) { Console.WriteLine($"{user.Name} - {user.Age}"); if (user.Languages != null) Console.WriteLine(string.Join(",", user.Languages)); } class Person { public ObjectId Id { get; set; } public string Name { get; set; } = ""; public int Age { get; set; } public List<string>? Languages { get; set; } }