W MongoDB $sort
etap potoku agregacji sortuje wszystkie dokumenty wejściowe i zwraca je do potoku w posortowanej kolejności.
Składnia
Składnia wygląda tak:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
Gdzie <sort order>
może być 1
rosnąco, -1
malejąco lub { $meta: "textScore" }
aby posortować według obliczonego textScore
metadane w porządku malejącym.
Przykładowe dane
Załóżmy, że mamy kolekcję o nazwie pets
z następującymi dokumentami:
{ "_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 }
Sortuj w porządku rosnącym
Aby posortować w porządku rosnącym, używamy 1
dla porządku sortowania.
Poniżej znajduje się przykład zapytania, które używa $sort
operator do sortowania tej kolekcji według weight
pole w kolejności rosnącej.
db.pets.aggregate([
{ $sort: { weight: 1 } }
])
Wynik:
{ "_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 }
Sortuj w porządku malejącym
Aby posortować w porządku malejącym, używamy -1
dla porządku sortowania.
db.pets.aggregate([
{ $sort: { weight: -1 } }
])
Wynik:
{ "_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 }
Sortuj według wielu pól
Aby posortować według więcej niż jednego pola, oddziel kombinację każdego pola/porządku sortowania przecinkiem.
Przykład
db.pets.aggregate([
{ $sort: { type: 1, weight: -1, _id: 1 } }
])
Wynik:
{ "_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 }
W tym przykładzie posortowaliśmy według type
najpierw pole w kolejności rosnącej, a następnie według weight
pole w kolejności malejącej, a następnie według _id
pole w porządku rosnącym.
Oznacza to, że jeśli istnieje wiele zwierząt tego samego typu, są one sortowane według ich weight
w kolejności malejącej. Jeśli istnieje wiele zwierząt o tym samym typie i wadze, te zwierzęta są sortowane według _id
pole w porządku rosnącym. Gdybyśmy nie uwzględnili _id
w procesie sortowania, wtedy te zwierzęta tego samego typu i wagi mogą pojawić się w dowolnej kolejności. Dzieje się tak za każdym razem, gdy uruchamiamy zapytanie. Bez posiadania pola sortowania w unikalnym polu (takim jak _id
pola), byłoby całkiem możliwe (nawet prawdopodobne), że wyniki będą zwracane w innej kolejności przy każdym uruchomieniu zapytania.
Sortowanie różnych typów
Porównując wartości różnych typów BSON, MongoDB stosuje następującą kolejność porównania, od najniższej do najwyższej:
- MinKey (typ wewnętrzny)
- Numer
- Liczby (int, long, double, dziesiętne)
- Symbol, ciąg
- Obiekt
- Tablica
- BinData
- Identyfikator obiektu
- Boole'a
- Data
- sygnatura czasowa
- Wyrażenie regularne
- MaxKey (typ wewnętrzny)
Załóżmy, że mamy kolekcję o nazwie posty z następującymi dokumentami:
{ "_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") }
Zauważ, że pierwsza date
pole zawiera ciąg daty, podczas gdy pozostałe dwa dokumenty używają obiektu Date.
Zauważ również, że ciąg daty zawiera dokładnie taką samą datę jak w dokumencie 3, a data ta jest późniejsza niż data w dokumencie 2.
Zastosujmy $sort
do date
pola tych dokumentów:
db.posts.aggregate([
{ $sort: { date: 1 } }
]).pretty()
Wynik:
{ "_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") }
W tym przypadku posortowaliśmy w porządku rosnącym, co oznacza, że wcześniejsze daty powinny być pierwsze. Jednak nasz pierwszy dokument zawiera ciąg daty zamiast obiektu Date, więc pojawił się jako pierwszy — mimo że jego data jest późniejsza niż data w dokumencie 2.
I znowu, ale w porządku malejącym:
db.posts.aggregate([
{ $sort: { date: -1 } }
]).pretty()
Wynik:
{ "_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" }
Po raz kolejny kolejność dat jest nie do zniesienia ze względu na różne typy danych.
Sortowanie metadanych wyniku tekstowego
Możesz użyć { $meta: "textScore" }
argument do sortowania według malejącego wyniku trafności przy użyciu $text
wyszukiwania.
Przykład
db.posts.aggregate(
[
{ $match: { $text: { $search: "funny" } } },
{ $sort: { score: { $meta: "textScore" }, title: -1 } }
]
).pretty()
Wynik:
{ "_id" : 2, "title" : "Animals", "body" : "Animals are funny things...", "date" : ISODate("2020-01-01T00:00:00Z") }
W tym przypadku tylko jeden dokument pasował do naszego zapytania.
W tym przykładzie posortowaliśmy według { $meta: "textScore" }
, a następnie title
w kolejności malejącej. Użyliśmy score
jako dowolna nazwa pola, ale jest ona ignorowana przez system zapytań.
Robienie $text
wyszukiwania takie jak to wymagają utworzenia indeksu tekstowego. Jeśli nie, IndexNotFound
zostanie zwrócony błąd.
Sortowanie zgrupowanych wyników
Wracając do naszych pets
kolekcji, możemy użyć $sort
etap po $group
etap, aby posortować grupę dokumentów według liczby wartości w określonym polu.
db.pets.aggregate([
{
$match: { weight: { $lt: 30 } }
},
{
$group: { _id: "$type", count: { $sum: 1 } }
},
{
$sort : { count : -1 }
}
])
Wynik:
{ "_id" : "Cat", "count" : 3 } { "_id" : "Dog", "count" : 2 }
Jednak może być lepiej, jeśli użyjesz $sortByCount
w takich przypadkach.
Więcej informacji
Więcej informacji znajdziesz w dokumentacji MongoDB.