In MongoDB, il $sort
la fase della pipeline di aggregazione ordina tutti i documenti di input e li restituisce alla pipeline in ordine ordinato.
Sintassi
La sintassi è questa:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
Dove <sort order>
può essere 1
per ascendente, -1
per decrescente o { $meta: "textScore" }
per ordinare in base al textScore
calcolato metadati in ordine decrescente.
Dati di esempio
Supponiamo di avere una collezione chiamata pets
con i seguenti documenti:
{ "_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 }
Ordina in ordine crescente
Per ordinare in ordine crescente, utilizziamo 1
per l'ordinamento.
Di seguito è riportato un esempio di una query che utilizza $sort
operatore per ordinare la raccolta in base al weight
campo in ordine crescente.
db.pets.aggregate([
{ $sort: { weight: 1 } }
])
Risultato:
{ "_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 }
Ordina in ordine decrescente
Per ordinare in ordine decrescente, utilizziamo -1
per l'ordinamento.
db.pets.aggregate([
{ $sort: { weight: -1 } }
])
Risultato:
{ "_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 }
Ordina per più campi
Per ordinare in base a più campi, separa ogni campo/combinazione di ordinamento con una virgola.
Esempio
db.pets.aggregate([
{ $sort: { type: 1, weight: -1, _id: 1 } }
])
Risultato:
{ "_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 questo esempio, abbiamo ordinato per type
campo prima in ordine crescente, poi in base al weight
campo in ordine decrescente, quindi dal _id
campo in ordine crescente.
Ciò significa che, se sono presenti più animali domestici dello stesso tipo, tali animali domestici vengono ordinati in base al loro weight
in ordine decrescente. Se ci sono più animali domestici con lo stesso tipo e peso, questi animali vengono ordinati in base al _id
campo in ordine crescente. Se non avessimo incluso il _id
campo nel processo di smistamento, gli animali domestici dello stesso tipo e peso potrebbero apparire in qualsiasi ordine. Questo è vero ogni volta che eseguiamo la query. Senza avere un campo di ordinamento su un campo univoco (come il _id
campo), sarebbe del tutto possibile (anche probabile) che i risultati tornino in un ordine diverso ogni volta che viene eseguita la query.
Ordinamento di tipi diversi
Quando si confrontano valori di diversi tipi BSON, MongoDB utilizza il seguente ordine di confronto, dal più basso al più alto:
- MinKey (tipo interno)
- Nulla
- Numeri (int, long, double, decimali)
- Simbolo, Stringa
- Oggetto
- Matrice
- BinData
- ID oggetto
- Booleano
- Data
- Data e ora
- Espressione regolare
- MaxKey (tipo interno)
Supponiamo di avere una raccolta chiamata post con i seguenti documenti:
{ "_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") }
Nota che la prima date
contiene una stringa di data, mentre gli altri due documenti utilizzano un oggetto Date.
Si noti inoltre che la stringa della data contiene esattamente la stessa data del documento 3 e questa data è successiva alla data nel documento 2.
Applichiamo $sort
alla date
campi di tali documenti:
db.posts.aggregate([
{ $sort: { date: 1 } }
]).pretty()
Risultato:
{ "_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 questo caso abbiamo ordinato in ordine crescente, il che significa che le date precedenti dovrebbero venire prima. Tuttavia, il nostro primo documento contiene una stringa di data anziché un oggetto Date, quindi è arrivato per primo, anche se la sua data è successiva alla data nel documento 2.
Eccolo di nuovo, ma in ordine decrescente:
db.posts.aggregate([
{ $sort: { date: -1 } }
]).pretty()
Risultato:
{ "_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" }
Ancora una volta, l'ordinamento della data è fuori luogo, a causa dei diversi tipi di dati.
Ordinamento metadati punteggio testo
Puoi usare il { $meta: "textScore" }
argomento da ordinare in base al punteggio di pertinenza decrescente quando si utilizza $text
ricerche.
Esempio
db.posts.aggregate(
[
{ $match: { $text: { $search: "funny" } } },
{ $sort: { score: { $meta: "textScore" }, title: -1 } }
]
).pretty()
Risultato:
{ "_id" : 2, "title" : "Animals", "body" : "Animals are funny things...", "date" : ISODate("2020-01-01T00:00:00Z") }
In questo caso, solo un documento ha soddisfatto la nostra richiesta.
In questo esempio, abbiamo ordinato per { $meta: "textScore" }
, quindi da title
in ordine decrescente. Abbiamo usato score
come nome di campo arbitrario, ma viene ignorato dal sistema di query.
Fare $text
ricerche come questa richiedono la creazione di un indice di testo. In caso contrario, un IndexNotFound
verrà restituito l'errore.
Ordinamento dei risultati raggruppati
Tornando ai nostri pets
raccolta, possiamo usare il $sort
fase dopo un $group
fase per ordinare un gruppo di documenti in base al numero di valori in un campo particolare.
db.pets.aggregate([
{
$match: { weight: { $lt: 30 } }
},
{
$group: { _id: "$type", count: { $sum: 1 } }
},
{
$sort : { count : -1 }
}
])
Risultato:
{ "_id" : "Cat", "count" : 3 } { "_id" : "Dog", "count" : 2 }
Tuttavia, potresti fare meglio a usare $sortByCount
operatore in questi casi.
Maggiori informazioni
Consulta la documentazione di MongoDB per ulteriori informazioni.