$sort (agregação)
Nesta página
Definição
Compatibilidade
Você pode utilizar o $sort
para implantações hospedadas nos seguintes ambientes:
MongoDB Atlas: o serviço totalmente gerenciado para implantações do MongoDB na nuvem
MongoDB Enterprise: a versão autogerenciada e baseada em assinatura do MongoDB
MongoDB Community: uma versão com código disponível, de uso gratuito e autogerenciada do MongoDB
Sintaxe
O estágio $sort
tem a seguinte forma de protótipo:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
$sort
recebe um documento que especifica o(s) campo(s) a ser(em) ordenado(s) e a respectiva ordem de classificação. <sort order>
pode ter um dos seguintes valores:
Valor | Descrição |
---|---|
1 | Ordem crescente. |
-1 | Ordem decrescente. |
{ $meta: "textScore" } |
|
Se estiver ordenando em vários campos, a ordem de classificação será avaliada da esquerda para a direita. Por exemplo, no formato acima, os documentos são ordenados pela primeira vez por <field1>
. Em seguida, os documentos com os mesmos valores <field1>
são ordenados por <field2>
.
Comportamento
Desempenho
$sort
é um estágio de bloqueio, o que faz com que o pipeline aguarde que todos os dados de entrada sejam recuperados para o estágio de bloqueio antes de processar os dados. Um estágio de bloqueio pode reduzir o desempenho porque reduz o processamento paralelo de um pipeline com vários estágios. Um estágio de bloqueio também pode usar quantidades significativas de memória para grandes conjuntos de dados.
Limites
Você pode ordenar o máximo de 32 chaves.
Fornecer um padrão de classificação com campos duplicados causa um erro.
Consistência da ordenação
O MongoDB não armazena documentos em uma collection em uma ordem específica. Ao ordenar em um campo que contém valores duplicados, os documentos que contêm esses valores podem ser retornados em qualquer ordem.
Se desejar uma ordem de classificação consistente, inclua pelo menos um campo em sua ordenação que contenha valores exclusivos. A maneira mais fácil de garantir isso é incluir o campo _id
em sua query de ordenação.
Considere a seguinte collection 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"}, ] )
O seguinte comando utiliza o estágio $sort
para ordenar no campo borough
:
db.restaurants.aggregate( [ { $sort : { borough : 1 } } ] )
Neste exemplo, a ordem de classificação pode ser inconsistente, pois o campo borough
contém valores duplicados para Manhattan
e Brooklyn
. Os documentos são retornados em ordem alfabética por borough
, mas a ordem desses documentos com valores duplicados para borough
pode não ser a mesma em várias execuções da mesma ordenação. Por exemplo, aqui estão os resultados de duas execuções diferentes do comando acima:
{ "_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" }
Embora os valores para borough
ainda estejam em ordem alfabética, a ordem dos documentos que contêm valores duplicados para borough
(ou seja, Manhattan
e Brooklyn
) não é a mesma.
Para ter uma classificação consistente, adicione um campo que contenha valores exclusivamente únicos à classificação. O comando a seguir usa a fase $sort
para classificação no campo borough
e também no campo _id
:
db.restaurants.aggregate( [ { $sort : { borough : 1, _id: 1 } } ] )
Como é sempre garantido que o campo _id
contenha exclusivamente valores únicos, a ordem de classificação retornada será sempre a mesma em várias execuções da mesma ordenação.
Classificar por um Campo de Array
Quando o MongoDB classifica documentos por um campo de valor de matriz, a chave de classificação depende se a classificação é crescente ou decrescente:
Em uma classificação ascendente, a chave de classificação é o menor valor na array.
Em uma classificação decrescente, a chave de classificação é o valor mais alto na array.
O filtro de consulta não afeta a seleção da chave de classificação.
Por exemplo, crie uma coleção shoes
com estes documentos:
db.shoes.insertMany( [ { _id: 'A', sizes: [ 7, 11 ] }, { _id: 'B', sizes: [ 8, 9, 10 ] } ] )
As seguintes consultas classificam os documentos pelo campo sizes
em ordem crescente e decrescente:
// Ascending sort db.shoes.aggregate( [ { $sort: { sizes: 1 } } ] ) // Descending sort db.shoes.aggregate( [ { $sort: { sizes: -1 } } ] )
Ambas as consultas anteriores retornam o documento com _id: 'A'
primeiro porque os tamanhos 7
e 11
são o menor e o maior nas entradas na matriz sizes
, respectivamente.
Exemplos
Ordem crescente/decrescente
Para o campo ou campos a serem ordenados, defina a ordem de classificação como 1
ou -1
para especificar uma classificação crescente ou decrescente, respectivamente, como no exemplo a seguir:
db.users.aggregate( [ { $sort : { age : -1, posts: 1 } } ] )
Esta operação coloca os documentos na collection users
em ordem decrescente, de acordo com o campo age
, e, em seguida, em ordem crescente, de acordo com o valor no campo posts
.
Ao comparar valores de diferentes tipos de BSON em operações de ordenação, o MongoDB usa a seguinte ordem de comparação, da menor para a maior:
MinKey (tipo interno)
Zero
Números (inteiros, longos, doubles, decimais)
Símbolo, string
Objeto
Array
BinData
ObjectId
Boolean
Data
Timestamp
Expressão regular
MaxKey (tipo interno)
Para obter detalhes sobre a ordem de comparação/classificação para tipos específicos, consulte Ordem de comparação/classificação.
Text Score Metadata Sort
Observação
$text
fornece recursos de query de texto para implantações autogerenciadas (não Atlas). Para dados hospedados no MongoDB Atlas, o MongoDB oferece uma solução aprimorada de query de texto completo, Atlas Search.
Para um pipeline que inclui $text
, você pode ordenar por pontuação de relevância decrescente usando a expressão { $meta: "textScore"
}
. No documento { <sort-key> }
, configure a expressão { $meta: "textScore" }
para um nome de campo arbitrário. O nome do campo é ignorado pelo sistema de query. Por exemplo:
db.users.aggregate( [ { $match: { $text: { $search: "operating" } } }, { $sort: { score: { $meta: "textScore" }, posts: -1 } } ] )
Esta operação usa o operador $text
para fazer a correspondência entre os documentos e, em seguida, ordena primeiro pelos metadados "textScore"
em ordem decrescente e, depois, pelo campo posts
em ordem decrescente. O nome do campo score
no documento de ordenação é ignorado pelo sistema de query. Neste pipeline, os metadados "textScore"
não são incluídos na projeção e não são retornados como parte dos documentos correspondentes. Consulte $meta
para mais informações.
$sort
Operador e memória
$sort
+ $limit
Otimização de memória
Quando um $sort
precede um $limit
e não há estágios intermediários que modifiquem o número de documentos, o otimizador pode unir o $limit
ao $sort
. Isso permite que a operação $sort
mantenha somente os principais resultados n
conforme progride, onde n
é o limite especificado, e garante que o MongoDB somente precise armazenar itens n
na memória. Essa otimização ainda se aplica quando allowDiskUse
for true
e os itens n
excederem o limite de memória de agregação.
As otimizações estão sujeitas a alterações entre as versões.
$sort
e restrições de memória
A partir do MongoDB 6.0, os estágios do pipeline que exigem mais de 100 megabytes de memória para execução gravam arquivos temporários no disco por padrão. Esses arquivos temporários duram durante a execução do pipeline e podem influenciar o espaço de armazenamento na sua instância. Em versões anteriores do MongoDB, você deve passar { allowDiskUse: true }
para find
individuais e comandos aggregate
para habilitar esse comportamento.
Somente find
e aggregate
comandos podem substituir o parâmetro allowDiskUseByDefault
por um ou outro:
Usando
{ allowDiskUse: true }
para permitir a gravação de arquivos temporários no disco quandoallowDiskUseByDefault
estiver definido comofalse
Usando
{ allowDiskUse: false }
para proibir a gravação de arquivos temporários no disco quandoallowDiskUseByDefault
estiver definido comotrue
Observação
Para o MongoDB Atlas, é recomendável configurar o auto-scaling de armazenamento para evitar que queries de longa duração preencham o armazenamento com arquivos temporários.
Se o Atlas cluster usar auto-scaling de armazenamento, os arquivos temporários podem fazer com que o cluster seja dimensionado para o próximo nível de armazenamento.
Para obter mais detalhes, consulte Limites do pipeline de agregação.
$sort
Operador e desempenho
O operador $sort
pode aproveitar um índice se ele for usado no primeiro estágio de um pipeline ou se for precedido apenas por um estágio $match
.
Quando você usa $sort
em um cluster fragmentado, cada fragmento ordena seus documentos de resultado usando um índice, quando disponível. Em seguida, o mongos
ou um dos fragmentos executa uma ordenação de mesclagem transmitida.