Сортировка

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

Для сортировки документов применяется метод Sort(), который в качестве параметра принимает определение сортировки. В качестве такого определения может выступать документ BsonDocument.

Для работы возьмем коллекцию, которая, допустим, называется "users" и которая хранит следующие данные:

{ "_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"] }

Например, отсортируем все документы по возрастанию по полю Age:

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 users = await collection.Find(new BsonDocument { }).Sort(new BsonDocument("Age", 1)).ToListAsync();

foreach (var user in users) Console.WriteLine(user);

Значение 1 в new BsonDocument("Age", 1) указывает на направление сортировки - по возрастанию. Так, в данном случае мы получим следующий консольный вывод:

{ "_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"] }
{ "_id" : ObjectId("63596dc76348749cac779373"), "Name" : "Tom", "Age" : 38, "Languages" : ["english", "german", "spanish"] }
{ "_id" : ObjectId("63596dc76348749cac779374"), "Name" : "Bob", "Age" : 42, "Languages" : ["english"] }

Если мы хотим выполнить сортировку по убыванию, то передается значение -1:

var users = await collection.Find(new BsonDocument { }).Sort(new BsonDocument("Age", -1)).ToListAsync();

Также можно использовать сокращенное определение сортировки в виде строки:

var users = await collection.Find("{}").Sort("{Age:1}").ToListAsync();

Дополнительно метод SortBy() сортирует по возрастанию. Он принимает делегат, который через параметр получает тип документа и возвращает поле/свойство документа, по которому идет сортировка. Например, сортировка по полю "Name":

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
var users = await collection.Find("{}").SortBy(d => d["Name"]).ToListAsync();

foreach (var user in users) Console.WriteLine(user);

Здесь коллекция типизирована типом BsonDocument, поэтому в делегат в методе SortBy передается объект BsonDocument, у которого обращаемся к полю Name.

Аналогично работает метод SortByDescending(), который сортирует по убыванию:

var users = await collection.Find("{}").SortByDescending(d => d["Name"]).ToListAsync();

Методы SortBy и SortByDescending особенно удобны, когда документ представляет объект кастомного типа. Например:

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 users = await collection.Find("{}")
    .SortBy(p=>p.Name)              // сортировка по возрастанию по Name
    .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; }

    public List<string>? Languages { get; set; }
}

В данном случае в качестве типа документов выступает класс Person. Консольный вывод:

Alice - 33
Bob - 42
Sam - 25
Tom - 38
Tom - 33

Последовательное применение нескольких критериев сортировки

Класс SortDefinitionBuilder позволяет последовательно применить несколько критериев сортировки:

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 во возврастанию, а затем по Age по убыванию
var sortDefinition = Builders<BsonDocument>.Sort.Ascending("Name").Descending("Age");
var users = await collection.Find("{}").Sort(sortDefinition).ToListAsync();

foreach (var user in users) Console.WriteLine(user);

В метод Sort() передается объект SortDefinitionBuilder, который определяется с помощью свойства Builders<BsonDocument>.Sort. С помощью метода Ascending можно указать поле сортировки по возрастанию, а в с помощью метода Descending - поле для сортировки по убыванию.

То есть в данном случае сначала документы сортируются по полю Name по возрастанию, а затем (если значение поля Name совпадает) - по полю Age по убыванию. И в данном случае мы получим следующий консольный вывод:

{ "_id" : ObjectId("63596dc76348749cac779376"), "Name" : "Alice", "Age" : 33 }
{ "_id" : ObjectId("63596dc76348749cac779374"), "Name" : "Bob", "Age" : 42, "Languages" : ["english"] }
{ "_id" : ObjectId("63596dc76348749cac779375"), "Name" : "Sam", "Age" : 25, "Languages" : ["english", "spanish"] }
{ "_id" : ObjectId("63596dc76348749cac779373"), "Name" : "Tom", "Age" : 38, "Languages" : ["english", "german", "spanish"] }
{ "_id" : ObjectId("63596dc76348749cac779377"), "Name" : "Tom", "Age" : 33, "Languages" : ["english"] }

Также мы можем воспользоваться перегруженными версиями и задать критерии фильтрации через лямбда-выражения:

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 во возврастанию, а затем по Age по убыванию
var sortDefinition = Builders<Person>.Sort.Ascending(p=>p.Name).Descending(p=>p.Age);
var users = await collection.Find("{}").Sort(sortDefinition).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; }

    public List<string>? Languages { get; set; }
}

Стоит отметить, что всю эту байду мы можем сократить следующим образом:

var users = await collection.Find("{}").Sort("{Name:1, Age:-1}").ToListAsync();
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850