In MongoDB is de $sort
aggregatiepijplijnfase sorteert alle invoerdocumenten en stuurt ze terug naar de pijplijn in gesorteerde volgorde.
Syntaxis
De syntaxis gaat als volgt:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
Waar <sort order>
kan 1
zijn voor oplopend, -1
voor aflopend, of { $meta: "textScore" }
om te sorteren op de berekende textScore
metagegevens in aflopende volgorde.
Voorbeeldgegevens
Stel dat we een verzameling hebben met de naam pets
met de volgende documenten:
{ "_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 }
Sorteren in oplopende volgorde
Om in oplopende volgorde te sorteren, gebruiken we 1
voor de sorteervolgorde.
Hieronder ziet u een voorbeeld van een zoekopdracht die gebruikmaakt van de $sort
operator om die verzameling te sorteren op weight
veld in oplopende volgorde.
db.pets.aggregate([
{ $sort: { weight: 1 } }
])
Resultaat:
{ "_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 }
Sorteren in aflopende volgorde
Om in aflopende volgorde te sorteren, gebruiken we -1
voor de sorteervolgorde.
db.pets.aggregate([
{ $sort: { weight: -1 } }
])
Resultaat:
{ "_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 }
Sorteren op meerdere velden
Om op meer dan één veld te sorteren, scheidt u elke combinatie van velden/sorteervolgorde met een komma.
Voorbeeld
db.pets.aggregate([
{ $sort: { type: 1, weight: -1, _id: 1 } }
])
Resultaat:
{ "_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 }
In dit voorbeeld hebben we gesorteerd op het type
veld eerst in oplopende volgorde, daarna met het weight
veld in aflopende volgorde, dan door de _id
veld in oplopende volgorde.
Dit betekent dat, als er meerdere huisdieren van hetzelfde type zijn, die huisdieren worden gesorteerd op hun weight
in aflopende volgorde. Als er meerdere huisdieren zijn met hetzelfde type en gewicht, dan worden die huisdieren gesorteerd op _id
veld in oplopende volgorde. Als we de _id
. niet hadden opgenomen veld in het sorteerproces, dan kunnen die huisdieren van hetzelfde type en gewicht in elke volgorde verschijnen. Dit geldt elke keer dat we de query uitvoeren. Zonder een sorteerveld op een uniek veld (zoals de _id
veld), is het heel goed mogelijk (zelfs waarschijnlijk) dat de resultaten elke keer dat de query wordt uitgevoerd in een andere volgorde terugkomen.
Verschillende soorten sorteren
Bij het vergelijken van waarden van verschillende BSON-typen gebruikt MongoDB de volgende vergelijkingsvolgorde, van laag naar hoog:
- MinKey (intern type)
- Null
- Getallen (ints, longs, doubles, decimals)
- Symbool, tekenreeks
- Object
- Array
- BinData
- Object-ID
- Booleaans
- Datum
- Tijdstempel
- Regelmatige expressie
- MaxKey (intern type)
Stel dat we een verzameling hebben met de naam posts met de volgende documenten:
{ "_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") }
Merk op dat de eerste date
veld een datumstring bevat, terwijl de andere twee documenten een Date-object gebruiken.
Merk ook op dat de datumreeks exact dezelfde datum bevat als document 3, en dat deze datum een latere datum is dan de datum in document 2.
Laten we $sort
toepassen naar de date
velden van die documenten:
db.posts.aggregate([
{ $sort: { date: 1 } }
]).pretty()
Resultaat:
{ "_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") }
In dit geval hebben we in oplopende volgorde gesorteerd, wat betekent dat eerdere datums eerst moeten komen. Ons eerste document bevat echter een datumstring in plaats van een Date-object, en dus kwam het eerst - ook al is de datum later dan de datum in document 2.
Hier is het weer, maar in aflopende volgorde:
db.posts.aggregate([
{ $sort: { date: -1 } }
]).pretty()
Resultaat:
{ "_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" }
Nogmaals, de volgorde van de datum is niet in orde vanwege de verschillende gegevenstypen.
Tekst Score Metadata Sorteren
U kunt de { $meta: "textScore" }
. gebruiken argument om te sorteren op aflopende relevantiescore bij gebruik van $text
zoekopdrachten.
Voorbeeld
db.posts.aggregate(
[
{ $match: { $text: { $search: "funny" } } },
{ $sort: { score: { $meta: "textScore" }, title: -1 } }
]
).pretty()
Resultaat:
{ "_id" : 2, "title" : "Animals", "body" : "Animals are funny things...", "date" : ISODate("2020-01-01T00:00:00Z") }
In dit geval kwam slechts één document overeen met onze zoekopdracht.
In dit voorbeeld hebben we gesorteerd op { $meta: "textScore" }
, dan door title
in aflopende volgorde. We gebruikten score
als een willekeurige veldnaam, maar dit wordt door het zoeksysteem genegeerd.
$text
doen zoekopdrachten als deze vereisen dat we een tekstindex hebben gemaakt. Zo niet, een IndexNotFound
fout wordt geretourneerd.
Gegroepeerde resultaten sorteren
Terug naar onze pets
verzameling, kunnen we de $sort
. gebruiken stage na een $group
stap om een groep documenten te sorteren op het aantal waarden in een bepaald veld.
db.pets.aggregate([
{
$match: { weight: { $lt: 30 } }
},
{
$group: { _id: "$type", count: { $sum: 1 } }
},
{
$sort : { count : -1 }
}
])
Resultaat:
{ "_id" : "Cat", "count" : 3 } { "_id" : "Dog", "count" : 2 }
U kunt echter beter de $sortByCount
. gebruiken operator in dergelijke gevallen.
Meer informatie
Zie de MongoDB-documentatie voor meer informatie.