В MongoDB, $sort Етапът на конвейера на агрегиране сортира всички входни документи и ги връща в конвейера в сортиран ред.
Синтаксис
Синтаксисът е така:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
Където <sort order> може да бъде 1 за възходящо, -1 за низходящо ниво или { $meta: "textScore" } за сортиране по изчисления textScore метаданни в низходящ ред.
Примерни данни
Да предположим, че имаме колекция, наречена pets със следните документи:
{ "_id" : 1, "name" : "Wag", "type" : "Dog", "weight" : 20 }
{ "_id" : 2, "name" : "Bark", "type" : "Dog", "weight" : 10 }
{ "_id" : 3, "name" : "Meow", "type" : "Cat", "weight" : 7 }
{ "_id" : 4, "name" : "Scratch", "type" : "Cat", "weight" : 8 }
{ "_id" : 5, "name" : "Bruce", "type" : "Kangaroo", "weight" : 100 }
{ "_id" : 6, "name" : "Hop", "type" : "Kangaroo", "weight" : 130 }
{ "_id" : 7, "name" : "Punch", "type" : "Kangaroo", "weight" : 200 }
{ "_id" : 8, "name" : "Snap", "type" : "Cat", "weight" : 12 }
{ "_id" : 9, "name" : "Ruff", "type" : "Dog", "weight" : 30 } Сортиране във възходящ ред
За да сортираме във възходящ ред, използваме 1 за реда на сортиране.
По-долу е даден пример за заявка, която използва $sort оператор за сортиране на тази колекция по weight поле във възходящ ред.
db.pets.aggregate([
{ $sort: { weight: 1 } }
]) Резултат:
{ "_id" : 3, "name" : "Meow", "type" : "Cat", "weight" : 7 }
{ "_id" : 4, "name" : "Scratch", "type" : "Cat", "weight" : 8 }
{ "_id" : 2, "name" : "Bark", "type" : "Dog", "weight" : 10 }
{ "_id" : 8, "name" : "Snap", "type" : "Cat", "weight" : 12 }
{ "_id" : 1, "name" : "Wag", "type" : "Dog", "weight" : 20 }
{ "_id" : 9, "name" : "Ruff", "type" : "Dog", "weight" : 30 }
{ "_id" : 5, "name" : "Bruce", "type" : "Kangaroo", "weight" : 100 }
{ "_id" : 6, "name" : "Hop", "type" : "Kangaroo", "weight" : 130 }
{ "_id" : 7, "name" : "Punch", "type" : "Kangaroo", "weight" : 200 } Сортиране в низходящ ред
За да сортираме в низходящ ред, използваме -1 за реда на сортиране.
db.pets.aggregate([
{ $sort: { weight: -1 } }
]) Резултат:
{ "_id" : 7, "name" : "Punch", "type" : "Kangaroo", "weight" : 200 }
{ "_id" : 6, "name" : "Hop", "type" : "Kangaroo", "weight" : 130 }
{ "_id" : 5, "name" : "Bruce", "type" : "Kangaroo", "weight" : 100 }
{ "_id" : 9, "name" : "Ruff", "type" : "Dog", "weight" : 30 }
{ "_id" : 1, "name" : "Wag", "type" : "Dog", "weight" : 20 }
{ "_id" : 8, "name" : "Snap", "type" : "Cat", "weight" : 12 }
{ "_id" : 2, "name" : "Bark", "type" : "Dog", "weight" : 10 }
{ "_id" : 4, "name" : "Scratch", "type" : "Cat", "weight" : 8 }
{ "_id" : 3, "name" : "Meow", "type" : "Cat", "weight" : 7 } Сортиране по множество полета
За да сортирате по повече от едно поле, отделете комбо всяко поле/ред за сортиране със запетая.
Пример
db.pets.aggregate([
{ $sort: { type: 1, weight: -1, _id: 1 } }
]) Резултат:
{ "_id" : 8, "name" : "Snap", "type" : "Cat", "weight" : 12 }
{ "_id" : 4, "name" : "Scratch", "type" : "Cat", "weight" : 8 }
{ "_id" : 3, "name" : "Meow", "type" : "Cat", "weight" : 7 }
{ "_id" : 9, "name" : "Ruff", "type" : "Dog", "weight" : 30 }
{ "_id" : 1, "name" : "Wag", "type" : "Dog", "weight" : 20 }
{ "_id" : 2, "name" : "Bark", "type" : "Dog", "weight" : 10 }
{ "_id" : 7, "name" : "Punch", "type" : "Kangaroo", "weight" : 200 }
{ "_id" : 6, "name" : "Hop", "type" : "Kangaroo", "weight" : 130 }
{ "_id" : 5, "name" : "Bruce", "type" : "Kangaroo", "weight" : 100 }
В този пример ние сортирахме по type първо във възходящ ред, след това по weight поле в низходящ ред, след това по _id поле във възходящ ред.
Това означава, че ако има няколко домашни любимци от един и същи тип, тези домашни любимци се сортират по тяхното weight в низходящ ред. Ако има няколко домашни любимци с един и същи вид и тегло, тогава тези домашни любимци се сортират по _id поле във възходящ ред. Ако не бяхме включили _id поле в процеса на сортиране, тогава тези домашни любимци от същия вид и тегло могат да се появят в произволен ред. Това е вярно всеки път, когато стартираме заявката. Без да има поле за сортиране в уникално поле (като _id поле), би било напълно възможно (дори вероятно) резултатите да се връщат в различен ред при всяко изпълнение на заявката.
Сортиране на различни типове
Когато сравнява стойности на различни типове BSON, MongoDB използва следния ред на сравнение, от най-ниския към най-високия:
- MinKey (вътрешен тип)
- Null
- Числа (цели, дълги, двойни, десетични)
- Символ, низ
- Обект
- Масив
- BinData
- ObjectId
- Булева
- Дата
- Часово клеймо
- Регулярен израз
- MaxKey (вътрешен тип)
Да предположим, че имаме колекция, наречена публикации със следните документи:
{
"_id" : 1,
"title" : "Web",
"body" : "Create a website with these three easy steps...",
"date" : "2021-01-01T00:00:00.000Z"
}
{
"_id" : 2,
"title" : "Animals",
"body" : "Animals are funny things...",
"date" : ISODate("2020-01-01T00:00:00Z")
}
{
"_id" : 3,
"title" : "Oceans",
"body" : "Oceans are wide and vast...",
"date" : ISODate("2021-01-01T00:00:00Z")
}
Забележете, че първата date полето съдържа низ от дата, докато другите два документа използват обект Date.
Също така имайте предвид, че низът с дата съдържа точно същата дата като документ 3 и тази дата е по-късна от датата в документ 2.
Нека приложим $sort до date полета на тези документи:
db.posts.aggregate([
{ $sort: { date: 1 } }
]).pretty() Резултат:
{
"_id" : 1,
"title" : "Web",
"body" : "Create a website with these three easy steps...",
"date" : "2021-01-01T00:00:00.000Z"
}
{
"_id" : 2,
"title" : "Animals",
"body" : "Animals are funny things...",
"date" : ISODate("2020-01-01T00:00:00Z")
}
{
"_id" : 3,
"title" : "Oceans",
"body" : "Oceans are wide and vast...",
"date" : ISODate("2021-01-01T00:00:00Z")
} В този случай сме сортирали във възходящ ред, което означава, че по-ранните дати трябва да са на първо място. Въпреки това, първият ни документ съдържа низ от дата вместо обект Date и така той дойде първи – въпреки че датата му е по-късна от датата в документ 2.
Ето го отново, но в низходящ ред:
db.posts.aggregate([
{ $sort: { date: -1 } }
]).pretty() Резултат:
{
"_id" : 3,
"title" : "Oceans",
"body" : "Oceans are wide and vast...",
"date" : ISODate("2021-01-01T00:00:00Z")
}
{
"_id" : 2,
"title" : "Animals",
"body" : "Animals are funny things...",
"date" : ISODate("2020-01-01T00:00:00Z")
}
{
"_id" : 1,
"title" : "Web",
"body" : "Create a website with these three easy steps...",
"date" : "2021-01-01T00:00:00.000Z"
} За пореден път подреждането на датите е неправилно, поради различните типове данни.
Сортиране на метаданни за текстова оценка
Можете да използвате { $meta: "textScore" } аргумент за сортиране по низходящ резултат за релевантност, когато използвате $text търсения.
Пример
db.posts.aggregate(
[
{ $match: { $text: { $search: "funny" } } },
{ $sort: { score: { $meta: "textScore" }, title: -1 } }
]
).pretty() Резултат:
{
"_id" : 2,
"title" : "Animals",
"body" : "Animals are funny things...",
"date" : ISODate("2020-01-01T00:00:00Z")
} В този случай само един документ съответства на нашата заявка.
В този пример ние сортирахме по { $meta: "textScore" } , след това по title в низходящ ред. Използвахме score като произволно име на поле, но това се игнорира от системата за заявки.
Правете $text търсене като това изисква да сме създали текстов индекс. Ако не, IndexNotFound грешка ще бъде върната.
Сортиране на групирани резултати
Връщайки се към нашите pets колекция, можем да използваме $sort етап след $group етап за сортиране на група документи по броя на стойностите в определено поле.
db.pets.aggregate([
{
$match: { weight: { $lt: 30 } }
},
{
$group: { _id: "$type", count: { $sum: 1 } }
},
{
$sort : { count : -1 }
}
]) Резултат:
{ "_id" : "Cat", "count" : 3 }
{ "_id" : "Dog", "count" : 2 }
Въпреки това може да е по-добре да използвате $sortByCount оператор в такива случаи.
Повече информация
Вижте документацията на MongoDB за повече информация.