En MongoDB, el $sort
la etapa de canalización de agregación ordena todos los documentos de entrada y los devuelve a la canalización en orden ordenado.
Sintaxis
La sintaxis es así:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
Donde <sort order>
puede ser 1
para ascender, -1
para descender, o { $meta: "textScore" }
para ordenar por el textScore
calculado metadatos en orden descendente.
Datos de muestra
Supongamos que tenemos una colección llamada pets
con los siguientes documentos:
{ "_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 }
Ordenar en orden ascendente
Para ordenar en orden ascendente, usamos 1
para el orden de clasificación.
A continuación se muestra un ejemplo de una consulta que utiliza el $sort
operador para ordenar esa colección por el weight
campo en orden ascendente.
db.pets.aggregate([
{ $sort: { weight: 1 } }
])
Resultado:
{ "_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 }
Ordenar en orden descendente
Para ordenar en orden descendente, usamos -1
para el orden de clasificación.
db.pets.aggregate([
{ $sort: { weight: -1 } }
])
Resultado:
{ "_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 }
Ordenar por campos múltiples
Para ordenar por más de un campo, separe cada combinación de campo/orden de clasificación con una coma.
Ejemplo
db.pets.aggregate([
{ $sort: { type: 1, weight: -1, _id: 1 } }
])
Resultado:
{ "_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 }
En este ejemplo, ordenamos por type
campo en orden ascendente primero, luego por el weight
campo en orden descendente, luego por el _id
campo en orden ascendente.
Esto significa que, si hay varias mascotas del mismo tipo, esas mascotas se ordenan por su weight
en orden descendente. Si hay varias mascotas con el mismo tipo y peso, esas mascotas se ordenan por el _id
campo en orden ascendente. Si no hubiéramos incluido el _id
en el proceso de clasificación, las mascotas del mismo tipo y peso podrían aparecer en cualquier orden. Esto es cierto cada vez que ejecutamos la consulta. Sin tener un campo de clasificación en un campo único (como el _id
campo), sería completamente posible (incluso probable) que los resultados regresaran en un orden diferente cada vez que se ejecuta la consulta.
Clasificación de diferentes tipos
Al comparar valores de diferentes tipos de BSON, MongoDB utiliza el siguiente orden de comparación, de menor a mayor:
- MinKey (tipo interno)
- Nulo
- Números (ints, largos, dobles, decimales)
- Símbolo, Cadena
- Objeto
- matriz
- BinData
- Id. de objeto
- Booleano
- Fecha
- Marca de tiempo
- Expresión regular
- MaxKey (tipo interno)
Supongamos que tenemos una colección llamada publicaciones con los siguientes documentos:
{ "_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") }
Observe que la primera date
El campo contiene una cadena de fecha, mientras que los otros dos documentos usan un objeto Fecha.
Observe también que la cadena de fecha contiene exactamente la misma fecha que el documento 3, y esta fecha es posterior a la fecha del documento 2.
Apliquemos $sort
a la date
campos de esos documentos:
db.posts.aggregate([
{ $sort: { date: 1 } }
]).pretty()
Resultado:
{ "_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") }
En este caso, ordenamos en orden ascendente, lo que significa que las fechas anteriores deben aparecer primero. Sin embargo, nuestro primer documento contiene una cadena de fecha en lugar de un objeto Fecha, por lo que llegó primero, aunque su fecha es posterior a la fecha del documento 2.
Aquí está de nuevo, pero en orden descendente:
db.posts.aggregate([
{ $sort: { date: -1 } }
]).pretty()
Resultado:
{ "_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" }
Una vez más, el orden de fechas está fuera de control debido a los diferentes tipos de datos.
Ordenación de metadatos de puntuación de texto
Puede usar el { $meta: "textScore" }
argumento para ordenar por puntaje de relevancia descendente al usar $text
búsquedas.
Ejemplo
db.posts.aggregate(
[
{ $match: { $text: { $search: "funny" } } },
{ $sort: { score: { $meta: "textScore" }, title: -1 } }
]
).pretty()
Resultado:
{ "_id" : 2, "title" : "Animals", "body" : "Animals are funny things...", "date" : ISODate("2020-01-01T00:00:00Z") }
En este caso, solo un documento coincidió con nuestra consulta.
En este ejemplo, ordenamos por { $meta: "textScore" }
, luego por title
en orden descendente. Usamos score
como un nombre de campo arbitrario, pero el sistema de consulta lo ignora.
Haciendo $text
búsquedas como esta requieren que hayamos creado un índice de texto. Si no, un IndexNotFound
se devolverá el error.
Ordenar resultados agrupados
Volviendo a nuestras pets
colección, podemos usar el $sort
etapa después de un $group
etapa para ordenar un grupo de documentos por el número de valores en un campo en particular.
db.pets.aggregate([
{
$match: { weight: { $lt: 30 } }
},
{
$group: { _id: "$type", count: { $sum: 1 } }
},
{
$sort : { count : -1 }
}
])
Resultado:
{ "_id" : "Cat", "count" : 3 } { "_id" : "Dog", "count" : 2 }
Sin embargo, es mejor que uses el $sortByCount
operador en tales casos.
Más información
Consulte la documentación de MongoDB para obtener más información.