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.