I MongoDB, $sort
aggregeringspipelinesteget sorterar alla indatadokument och returnerar dem till pipelinen i sorterad ordning.
Syntax
Syntaxen ser ut så här:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
Där 1
för stigande, -1
för fallande, eller { $meta:"textScore" }
för att sortera efter den beräknade textScore
metadata i fallande ordning.
Exempeldata
Anta att vi har en samling som heter husdjur
med följande dokument:
{ "_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 }
Sortera i stigande ordning
För att sortera i stigande ordning använder vi 1
för sorteringsordningen.
Nedan är ett exempel på en fråga som använder $sort
operatör för att sortera samlingen efter vikt
fältet i stigande ordning.
db.pets.aggregate([
{ $sort: { weight: 1 } }
])
Resultat:
{ "_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 }
Sortera i fallande ordning
För att sortera i fallande ordning använder vi -1
för sorteringsordningen.
db.pets.aggregate([
{ $sort: { weight: -1 } }
])
Resultat:
{ "_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 }
Sortera efter flera fält
För att sortera efter mer än ett fält, separera varje fält/sorteringsordningskombo med ett kommatecken.
Exempel
db.pets.aggregate([
{ $sort: { type: 1, weight: -1, _id: 1 } }
])
Resultat:
{ "_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 }
I det här exemplet sorterade vi efter typ
fältet i stigande ordning först, sedan efter vikt
fältet i fallande ordning, sedan efter _id
fältet i stigande ordning.
Detta innebär att om det finns flera husdjur av samma typ, sorteras dessa husdjur efter deras vikt
i fallande ordning. Om det finns flera husdjur med både samma typ och vikt, sorteras dessa husdjur efter _id
fältet i stigande ordning. Om vi inte hade inkluderat _id
fältet i sorteringsprocessen, kan dessa husdjur av samma typ och vikt dyka upp i valfri ordning. Detta är sant varje gång vi kör frågan. Utan att ha ett sorteringsfält på ett unikt fält (som _id
). fältet), skulle det vara fullt möjligt (även troligt) att resultaten skulle komma tillbaka i en annan ordning varje gång frågan kördes.
Sortera olika typer
När man jämför värden för olika BSON-typer använder MongoDB följande jämförelseordning, från lägsta till högsta:
- MinKey (intern typ)
- Null
- Siffror (ints, longs, doubles, decimals)
- Symbol, sträng
- Objekt
- Array
- BinData
- ObjectId
- Boolesk
- Datum
- Tidsstämpel
- Reguljärt uttryck
- MaxKey (intern typ)
Anta att vi har en samling som kallas inlägg med följande dokument:
{ "_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") }
Observera att det första datumet
fältet innehåller en datumsträng, medan de andra två dokumenten använder ett Date-objekt.
Observera också att datumsträngen innehåller exakt samma datum som dokument 3, och detta datum är ett senare datum än datumet i dokument 2.
Låt oss tillämpa $sort
till datum
fält i dessa dokument:
db.posts.aggregate([
{ $sort: { date: 1 } }
]).pretty()
Resultat:
{ "_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") }
I det här fallet sorterade vi i stigande ordning, vilket betyder att tidigare datum bör komma först. Men vårt första dokument innehåller en datumsträng istället för ett Date-objekt, så det kom först – även om dess datum är senare än datumet i dokument 2.
Här är den igen, men i fallande ordning:
db.posts.aggregate([
{ $sort: { date: -1 } }
]).pretty()
Resultat:
{ "_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" }
Än en gång är datumbeställningen ur funktion, på grund av de olika datatyperna.
Sortera textresultatmetadata
Du kan använda { $meta:"textScore" }
argument för att sortera efter fallande relevanspoäng när du använder $text
sökningar.
Exempel
db.posts.aggregate(
[
{ $match: { $text: { $search: "funny" } } },
{ $sort: { score: { $meta: "textScore" }, title: -1 } }
]
).pretty()
Resultat:
{ "_id" : 2, "title" : "Animals", "body" : "Animals are funny things...", "date" : ISODate("2020-01-01T00:00:00Z") }
I det här fallet matchade bara ett dokument vår fråga.
I det här exemplet sorterade vi efter { $meta:"textScore" }
, sedan efter titel
i fallande ordning. Vi använde score
som ett godtyckligt fältnamn, men detta ignoreras av frågesystemet.
Gör $text
sökningar som denna kräver att vi har skapat ett textindex. Om inte, en IndexNotFound
fel kommer att returneras.
Sortera grupperade resultat
Går tillbaka till våra husdjur
samling kan vi använda $sort
steg efter en $grupp
steg för att sortera en grupp av dokument efter antalet värden i ett visst fält.
db.pets.aggregate([
{
$match: { weight: { $lt: 30 } }
},
{
$group: { _id: "$type", count: { $sum: 1 } }
},
{
$sort : { count : -1 }
}
])
Resultat:
{ "_id" : "Cat", "count" : 3 } { "_id" : "Dog", "count" : 2 }
Det kan dock vara bättre att använda $sortByCount
operatör i sådana fall.
Mer information
Se MongoDB-dokumentationen för mer information.