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.