No MongoDB, o
$sort
O estágio de pipeline de agregação classifica todos os documentos de entrada e os retorna ao pipeline em ordem de classificação. Sintaxe
A sintaxe fica assim:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
Onde
<sort order>
pode ser 1
para ascendente, -1
para decrescente ou { $meta: "textScore" }
para classificar pelo textScore
calculado metadados em ordem decrescente. Dados de amostra
Suponha que tenhamos uma coleção chamada
pets
com os seguintes 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 }
Classificar em ordem crescente
Para classificar em ordem crescente, usamos
1
para a ordem de classificação. Abaixo está um exemplo de uma consulta que usa o
$sort
operador para classificar essa coleção pelo weight
campo em ordem crescente. 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 }
Classificar em ordem decrescente
Para classificar em ordem decrescente, usamos
-1
para a ordem de classificação. 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 }
Classificar por vários campos
Para classificar por mais de um campo, separe cada combinação de campo/ordem de classificação com uma vírgula.
Exemplo
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 }
Neste exemplo, classificamos pelo
type
primeiro em ordem crescente, depois pelo weight
campo em ordem decrescente, depois pelo _id
campo em ordem crescente. Isso significa que, se houver vários animais de estimação do mesmo tipo, esses animais de estimação serão classificados por seu
weight
por ordem decrescente. Se houver vários animais de estimação com o mesmo tipo e peso, esses animais serão classificados pelo _id
campo em ordem crescente. Se não tivéssemos incluído o _id
campo no processo de classificação, os animais de estimação do mesmo tipo e peso podem aparecer em qualquer ordem. Isso é verdade toda vez que executamos a consulta. Sem ter um campo de classificação em um campo exclusivo (como o _id
campo), seria inteiramente possível (até mesmo provável) que os resultados voltassem em uma ordem diferente cada vez que a consulta fosse executada. Classificando tipos diferentes
Ao comparar valores de diferentes tipos de BSON, o MongoDB usa a seguinte ordem de comparação, do menor para o maior:
- MinKey (tipo interno)
- Nulo
- Números (ints, longs, doubles, decimals)
- Símbolo, string
- Objeto
- Matriz
- BinData
- ObjectID
- Booleano
- Data
- Carimbo de data e hora
- Expressão regular
- MaxKey (tipo interno)
Suponha que tenhamos uma coleção chamada posts com os seguintes 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 a primeira
date
contém uma string de data, enquanto os outros dois documentos usam um objeto Date. Observe também que a string de data contém exatamente a mesma data do documento 3 e essa data é posterior à data do documento 2.
Vamos aplicar
$sort
para a date
campos desses 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") }
Nesse caso, classificamos em ordem crescente, o que significa que as datas anteriores devem vir primeiro. No entanto, nosso primeiro documento contém uma string de data em vez de um objeto Date e, portanto, veio primeiro – mesmo que sua data seja posterior à data no documento 2.
Aqui está novamente, mas em ordem decrescente:
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" }
Mais uma vez, a ordenação de datas está fora de controle, devido aos diferentes tipos de dados.
Classificação de metadados de pontuação de texto
Você pode usar o
{ $meta: "textScore" }
argumento para classificar por pontuação de relevância decrescente ao usar $text
pesquisas. Exemplo
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") }
Nesse caso, apenas um documento correspondeu à nossa consulta.
Neste exemplo, classificamos por
{ $meta: "textScore" }
, depois por title
por ordem decrescente. Usamos score
como um nome de campo arbitrário, mas isso é ignorado pelo sistema de consulta. Fazendo
$text
pesquisas como essa exigem que tenhamos criado um índice de texto. Caso contrário, um IndexNotFound
erro será retornado. Classificando resultados agrupados
Voltando aos nossos
pets
coleção, podemos usar o $sort
estágio após um $group
estágio para classificar um grupo de documentos pelo número de valores em um campo específico. 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 }
No entanto, talvez seja melhor usar o
$sortByCount
operador nesses casos. Mais informações
Consulte a documentação do MongoDB para obter mais informações.