В 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 за повече информация.