Docs Menu
Docs Home
/ /
Etapas de la pipeline de agregación

$sort (agregación)

$sort

Ordena todos los documentos de entrada y los devuelve al pipeline en orden.

Puedes usar $sort para implementaciones alojadas en los siguientes entornos:

  • MongoDB Atlas: El servicio totalmente gestionado para implementaciones de MongoDB en la nube

  • MongoDB Enterprise: La versión basada en suscripción y autogestionada de MongoDB

  • MongoDB Community: La versión de MongoDB con código fuente disponible, de uso gratuito y autogestionada.

La etapa $sort tiene la siguiente forma de prototipo:

{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }

$sort toma un documento que especifica los campos por orden y el orden de clasificación respectivo. <sort order> puede tener uno de los siguientes valores:

Valor
Descripción

1

Ordenar de forma ascendente.

-1

Ordenar de forma descendente.

{ $meta: "textScore" }

Ordenar por los metadatos textScore calculados en orden descendente
orden. Consulte Orden de metadatos de puntuación de texto para ver un ejemplo.

Si se ordena en varios campos, el orden de clasificación se evalúa de izquierda a derecha. Por ejemplo, en el formulario anterior, los documentos se ordenan primero por <field1>. Luego, los documentos con los mismos valores <field1> se ordenan adicionalmente por <field2>.

$sort es una etapa de bloqueo, que hace que el pipeline espere a que se recuperen todos los datos de entrada para la etapa de bloqueo antes del procesamiento de los datos. Una etapa de bloqueo puede reducir el rendimiento porque disminuye el procesamiento paralelo en un pipeline con múltiples etapas. Una etapa de bloqueo también puede utilizar cantidades sustanciales de memoria para grandes conjuntos de datos.

  • Puedes ordenar sobre un máximo de 32 claves.

  • Proveer un patrón de ordenación con campos duplicados causa un error.

MongoDB no almacena documentos en una colección en un orden específico. Al ordenar en un campo que contiene valores duplicados, los documentos que contienen esos valores pueden ser devueltos en cualquier orden.

Si se desea un orden de clasificación coherente, se debe incluir al menos un campo en la clasificación que contenga valores únicos. La forma más sencilla de garantizar esto es incluir el campo _id en la query de ordenación.

Considere la siguiente colección restaurant:

db.restaurants.insertMany( [
{ _id: 1, name: "Central Park Cafe", borough: "Manhattan"},
{ _id: 2, name: "Rock A Feller Bar and Grill", borough: "Queens"},
{ _id: 3, name: "Empire State Pub", borough: "Brooklyn"},
{ _id: 4, name: "Stan's Pizzaria", borough: "Manhattan"},
{ _id: 5, name: "Jane's Deli", borough: "Brooklyn"},
] )

El siguiente comando utiliza la etapa $sort para ordenar en el campo borough:

db.restaurants.aggregate(
[
{ $sort : { borough : 1 } }
]
)

En este ejemplo, el orden de clasificación puede ser inconsistente, ya que el campo borough contiene valores duplicados tanto para Manhattan como para Brooklyn. Los documentos se devuelven en orden alfabético por borough, pero el orden de aquellos documentos con valores duplicados para borough podría no ser el mismo en múltiples ejecuciones del mismo ordenamiento. Por ejemplo, aquí están los resultados de dos ejecuciones diferentes del comando mencionado anteriormente:

{ _id: 3, name: "Empire State Pub", borough: "Brooklyn" }
{ _id: 5, name: "Jane's Deli", borough: "Brooklyn" }
{ _id: 1, name: "Central Park Cafe", borough: "Manhattan" }
{ _id: 4, name: "Stan's Pizzaria", borough: "Manhattan" }
{ _id: 2, name: "Rock A Feller Bar and Grill", borough: "Queens" }
{ _id: 5, name: "Jane's Deli", borough: "Brooklyn" }
{ _id: 3, name: "Empire State Pub", borough: "Brooklyn" }
{ _id: 4, name: "Stan's Pizzaria", borough: "Manhattan" }
{ _id: 1, name: "Central Park Cafe", borough: "Manhattan" }
{ _id: 2, name: "Rock A Feller Bar and Grill", borough: "Queens" }

Aunque los valores para borough aún se ordenan alfabéticamente, el orden de los documentos que contienen valores duplicados para borough (es decir, Manhattan y Brooklyn) no son lo mismo.

Para lograr una clasificación coherente, agrega un campo que contenga valores exclusivamente únicos a la clasificación. El siguiente comando usa la etapa $sort para ordenar tanto en el campo borough como en el campo _id:

db.restaurants.aggregate(
[
{ $sort : { borough : 1, _id: 1 } }
]
)

Dado que siempre se garantiza que el campo _id contendrá valores exclusivamente únicos, el orden de clasificación devuelto siempre será el mismo en múltiples ejecuciones del mismo ordenamiento.

Cuando MongoDB ordena documentos por un campo cuyo valor es un arreglo, la clave de ordenación depende de si el orden es ascendente o descendente:

  • En una ordenación ascendente, la clave de ordenación es el valor más bajo del arreglo.

  • En una ordenación descendente, la clave de ordenación es el valor más alto del arreglo.

El filtro de query no afecta la selección de la clave de ordenación.

Por ejemplo, cree una colección shoes con estos documentos:

db.shoes.insertMany( [
{ _id: 'A', sizes: [ 7, 11 ] },
{ _id: 'B', sizes: [ 8, 9, 10 ] }
] )

Las siguientes queries ordenan los documentos por el campo sizes en orden ascendente y descendente:

// Ascending sort
db.shoes.aggregate( [
{
$sort: { sizes: 1 }
}
] )
// Descending sort
db.shoes.aggregate( [
{
$sort: { sizes: -1 }
}
] )

Ambas queries anteriores devuelven el documento con _id: 'A' primero porque los tamaños 7 y 11 son el más bajo y el más alto en las entradas del arreglo sizes, respectivamente.

Cuando filtra y ordena por un campo que contiene un arreglo, el filtro no afecta el valor utilizado como clave de ordenación. La ordenación siempre considera todos los valores del arreglo como posibles llaves de ordenación.

Por ejemplo, la siguiente query busca zapatos con tallas mayores a 9 y ordena los resultados por talla en orden ascendente:

db.shoes.aggregate( [
{
$match: { sizes: { $gt: 9 } }
},
{
$sort: { sizes: 1 }
}
] )

El orden es ascendente, lo que significa que la clave de ordenación es el valor más bajo en el arreglo sizes:

  • En el documento _id: 'A', el elemento sizes de menor valor es 7. Este valor se utiliza como clave de ordenación aunque no coincida con el filtro { sizes: { $gt: 9 }.

  • En el documento _id: 'B', el elemento sizes de menor valor es 8. De manera similar, este valor se utiliza como clave de ordenación incluso si no coincide con el filtro.

La query devuelve el documento con _id: 'A' primero.

Tip

Ordenar solo por valores coincidentes

Para considerar únicamente los valores coincidentes como posibles claves de ordenación, puedes generar un nuevo campo que contenga dichos valores y ordenar por ese campo. Para obtener más información, consulta estas etapas y expresiones del pipeline:

Cuando un $sort precede a un $limit y no hay etapas intermedias que modifiquen el número de documentos, el optimizador puede fusionar el $limit con el $sort. Esto permite que la operación de $sort solo mantenga los n mejores resultados a medida que avanza, donde n es el límite especificado, y garantiza que MongoDB solo necesite almacenar n elementos en memoria. Esta optimización sigue aplicándose cuando allowDiskUse es true y los elementos de n superan el límite de memoria de agregación.

Las optimizaciones están sujetas a cambios entre versiones.

A partir de MongoDB 6.0, las etapas de la canalización que requieren más de 100 megabytes de memoria para ejecutarse escriben archivos temporales en el disco de forma predeterminada. Estos archivos temporales duran mientras se ejecuta la canalización y pueden afectar el espacio de almacenamiento de la instancia. En versiones anteriores de MongoDB, se debía pasar { allowDiskUse: true } a los comandos find y aggregate para habilitar este comportamiento.

Los comandos individuales find y aggregate pueden anular el parámetro allowDiskUseByDefault de las siguientes maneras:

  • Se utiliza { allowDiskUse: true } para permitir la escritura de archivos temporales en el disco cuando allowDiskUseByDefault se establece en false

  • Se utiliza { allowDiskUse: false } para prohibir la escritura de archivos temporales en el disco cuando allowDiskUseByDefault esté configurado en true

Nota

Para MongoDB Atlas, se recomienda configurar el escalado automático de almacenamiento para evitar que los queries de larga duración llenen el almacenamiento con archivos temporales.

Si su clúster de Atlas utiliza el escalado automático de almacenamiento, los archivos temporales pueden hacer que su clúster escale al siguiente nivel de almacenamiento.

Para obtener más información, consulte Límites de pipeline de agregación.

El operador $sort puede aprovechar un índice si se utiliza en la primera etapa de una pipeline o si sólo está precedido por una etapa $match.

Cuando utiliza el $sort en un clúster particionado, cada partición ordena sus documentos de resultado a través de un índice cuando esté disponible. Luego, el mongos o uno de los fragmentos realiza un ordenamiento por fusión en flujo.

Para los campos a ordenar, establezca el orden de clasificación en 1 o -1 para especificar un orden ascendente o descendente, respectivamente, como en el siguiente ejemplo:

db.users.aggregate(
[
{ $sort : { age : -1, posts: 1 } }
]
)

Esta operación ordena los documentos de la colección users, en orden descendente según el campo age y luego en orden ascendente según el valor en el campo posts.

Al comparar valores de diferentes BSON types en operaciones de ordenación, MongoDB utiliza el siguiente orden de comparación, de menor a mayor:

  1. MinKey (tipo interno)

  2. Nulo

  3. Números (enteros, largos, dobles, decimales)

  4. Símbolo, string

  5. Objeto

  6. Arreglo

  7. BinData

  8. ObjectId

  9. Booleano

  10. fecha

  11. Marca de tiempo

  12. Expresión regular

  13. Código JavaScript

  14. Código JavaScript con alcance

  15. MaxKey (tipo interno)

Para obtener detalles sobre el orden de comparación o clasificación para tipos específicos, consulte el orden de comparación o clasificación.

Nota

$text Proporciona funciones de consulta de texto para implementaciones autogestionadas (no Atlas). Para los datos alojados en MongoDB Atlas, MongoDB ofrece una solución mejorada de consulta de texto completo: Atlas Search.

Para un pipeline que incluye $text, puede ordenar por puntuación de relevancia descendente mediante la expresión { $meta: "textScore" }. En el documento { <sort-key> }, establezca la expresión { $meta: "textScore" } en un nombre de campo arbitrario. El sistema de query ignora el nombre del campo. Por ejemplo:

db.users.aggregate(
[
{ $match: { $text: { $search: "operating" } } },
{ $sort: { score: { $meta: "textScore" }, posts: -1 } }
]
)

Esta operación utiliza el operador $text para hacer coincidir los documentos, y luego ordena primero por los metadatos "textScore" en orden descendente, y luego por el campo posts en orden descendente. El sistema de query ignora el nombre del campo score en el documento de ordenación. En este pipeline, los metadatos "textScore" no se incluyen en la proyección y no se devuelven como parte de los documentos coincidentes. Consulte $meta para obtener más información.

Los ejemplos de C# en esta página utilizan la base de datos sample_mflix de los conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, consulta Primeros pasos en la documentación del controlador de MongoDB .NET/C#.

La siguiente clase Movie modela los documentos en la colección sample_mflix.movies:

public class Movie
{
public ObjectId Id { get; set; }
public int Runtime { get; set; }
public string Title { get; set; }
public string Rated { get; set; }
public List<string> Genres { get; set; }
public string Plot { get; set; }
public ImdbData Imdb { get; set; }
public int Year { get; set; }
public int Index { get; set; }
public string[] Comments { get; set; }
[BsonElement("lastupdated")]
public DateTime LastUpdated { get; set; }
}

Nota

ConventionPack para Pascal Case

Las clases de C# en esta página utilizan Pascal case para los nombres de sus propiedades, pero los nombres de los campos en la colección de MongoDB utilizan camel case. Para tener en cuenta esta diferencia, se puede usar el siguiente código para registrar un ConventionPack cuando la aplicación se inicie:

var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);

Para usar el controlador MongoDB.NET/C# para agregar una $sort etapa a una canalización de agregación, llame a Sort()método en un PipelineDefinition objeto.

En el siguiente ejemplo, se crea una etapa de pipeline que ordena los documentos de entrada Movie, primero en orden descendente por el campo Year, y luego en orden ascendente por el campo Title:

var pipeline = new EmptyPipelineDefinition<Movie>()
.Sort(Builders<Movie>.Sort.Combine(
Builders<Movie>.Sort.Descending(m => m.Year),
Builders<Movie>.Sort.Ascending(m => m.Title)));

Los ejemplos de Node.js en esta página utilizan la base de datos sample_mflix de los conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, consulte Primeros pasos en la documentación del controlador de MongoDB Node.js.

Para utilizar el controlador de MongoDB Node.js para agregar una etapa de $sort a una canalización de agregación, utilice el Operador $sort en un objeto de canalización.

En el siguiente ejemplo, se crea una etapa de pipeline que ordena los documentos de la entrada movie, primero en orden descendente según el campo year y luego en orden ascendente según el campo title. A continuación, se ejecuta el pipeline de agregación:

const pipeline = [{ $sort: { year: -1, title: 1 } }];
const cursor = collection.aggregate(pipeline);
return cursor;

Para ver ejemplos completos de agregación que utilizan la etapa $sort, consulte los Tutoriales completos de la canalización de agregación.

Volver

$skip

En esta página