sql >> Base de Datos >  >> NoSQL >> MongoDB

MongoDB $ ordenar

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:

  1. MinKey (tipo interno)
  2. Nulo
  3. Números (ints, largos, dobles, decimales)
  4. Símbolo, Cadena
  5. Objeto
  6. matriz
  7. BinData
  8. Id. de objeto
  9. Booleano
  10. Fecha
  11. Marca de tiempo
  12. Expresión regular
  13. 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.