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
$sort tem o seguinte formato:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }$sort requer um documento que especifica os campos pelos quais ordenar e a respectiva ordem de classificação. <sort order> pode ter um dos seguintes valores:
Valor | Descrição |
|---|---|
| Ordem crescente. |
| Ordem decrescente. |
| Ordene pelos metadados |
Ao classificar em vários campos, o $sort avalia a ordem de classificação da esquerda para a direita. Os documento são primeiro classificados por <field1>, então os documento com o mesmo valor de <field1> são classificados por <field2>.
Comportamento
Desempenho
$sort é um estágio de bloqueio, que faz com que o pipeline espere 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 substanciais 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.
A operação $sort não é uma "classificação estável", o que significa que documentos com chaves de classificação equivalentes não têm garantia de permanecer na mesma ordem relativa na saída como estavam na entrada.
Se o campo especificado nos critérios de classificação não existir em dois documentos, então o valor pelo qual eles são classificados é o mesmo. Os dois documentos 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 coleção movies no conjunto de dados de amostra sample_mflix. O comando a seguir classifica os filmes lançados em 1925 ou 1926 por year em ordem crescente:
db.movies.aggregate( [ { $match: { year: { $in: [ 1925, 1926 ] } } }, { $sort: { year: 1 } }, { $project: { _id: 0, title: 1, year: 1 } }] )Como o campo year tem valores duplicados para 1925 e 1926, os documento com o mesmo valor podem ser classificados de forma diferente entre as execuções. Por exemplo, duas execuções do comando anterior produzem ordenações diferentes:
[ { title: "Clash of the Wolves", year: 1925 }, { title: "Lady Windermere's Fan", year: 1925 }, { title: "Grass: A Nation's Battle for Life", year: 1925 }, { title: "Beau Geste", year: 1926 }, { title: "The Black Pirate", year: 1926 }, { title: "Ella Cinders", year: 1926 }, { title: "For Heaven's Sake", year: 1926 }, { title: "The Son of the Sheik", year: 1926 }, { title: "The Strong Man", year: 1926 }][ { title: "Lady Windermere's Fan", year: 1925 }, { title: "Grass: A Nation's Battle for Life", year: 1925 }, { title: "Clash of the Wolves", year: 1925 }, { title: "The Strong Man", year: 1926 }, { title: "The Black Pirate", year: 1926 }, { title: "Ella Cinders", year: 1926 }, { title: "Beau Geste", year: 1926 }, { title: "The Son of the Sheik", year: 1926 }, { title: "For Heaven's Sake", year: 1926 }]Uma operação classifica os valores para year em ordem crescente, mas a ordem dos documentos que contêm valores duplicados para year não é a mesma. Por exemplo, valores duplicados para 1925 e 1926.
Para obter uma ordenação consistente, adicione um campo que contenha apenas valores exclusivos à ordenação. O comando a seguir ordena tanto no campo year quanto no campo _id:
db.movies.aggregate( [ { $match: { year: { $in: [ 1925, 1926 ] } } }, { $sort: { year: 1, _id: 1 } }] )O campo _id sempre contém valores exclusivos e a ordem de classificação é consistente para várias execuções de classificaçã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, considere estes documento da coleção movies no conjunto de dados de amostra sample_mflix:
{ _id: ObjectId("573a1395f29313caabce166c"), title: "The Comancheros", genres: [ "Action", "Western", "Adventure" ]}{ _id: ObjectId("573a1391f29313caabcd8521"), title: "The Son of the Sheik", genres: [ "Adventure", "Drama" ]}As seguintes consultas classificam os documentos pelo campo genres em ordem crescente e decrescente:
// Ascending sortdb.movies.aggregate( [ { $match: { title: { $in: [ "The Comancheros", "The Son of the Sheik" ] } } }, { $sort: { genres: 1 } }] )// Descending sortdb.movies.aggregate( [ { $match: { title: { $in: [ "The Comancheros", "The Son of the Sheik" ] } } }, { $sort: { genres: -1 } }] )Ambas as consultas anteriores retornam The Comancheros primeiro porque Action e Western são as entradas mais baixas e mais altas em sua matriz genres, respectivamente.
Filtrar e ordenar por um campo de Array
Quando você filtra e ordena por um campo que contém um array, o filtro não altera o valor utilizado como chave de ordenação. A ordenação sempre considera todos os valores do array como possíveis chaves de ordenação.
Por exemplo, a query a seguir encontra filmes cujo array genres inclui "Drama" ou "Western" e ordena os resultados por genres em ordem crescente:
db.movies.aggregate( [ { $match: { title: { $in: [ "The Comancheros", "The Son of the Sheik" ] }, genres: { $in: [ "Drama", "Western" ] } } }, { $sort: { genres: 1 } }] )A ordenação é crescente. A chave de classificação é o primeiro valor no array genres quando classificado alfabeticamente:
Em
The Comancheros, o primeiro elementogenreséAction. Este valor é utilizado como chave de ordenação, mesmo que não corresponda ao filtro{ genres: { $in: [ "Drama", "Western" ] } }.Em
The Son of the Sheik, o primeiro elementogenreséAdventure. Da mesma forma, esta operação utilizaAdventurecomo chave de ordenação, mesmo que não corresponda ao filtro.
A query retorna The Comancheros primeiro.
Dica
Ordenar somente por valores correspondentes
Para considerar apenas os valores correspondentes como chaves de ordenação potenciais, você pode criar um novo campo contendo esses valores e ordenar com base nesse campo. Para obter mais informações, consulte estes estágios e expressões do pipeline:
Operador $sort e memória
Otimização de memória com $sort e $limit
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
Estágios de pipeline que exigem mais de 100 megabytes de memória para executar, gravam arquivos temporários em disco por padrão. Esses arquivos temporários duram durante a execução do pipeline e podem influenciar o espaço de armazenamento em sua instância.
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 quandoallowDiskUseByDefaultestiver definido comofalseUsando
{ allowDiskUse: false }para proibir a gravação de arquivos temporários no disco quandoallowDiskUseByDefaultestiver 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.
Uso de $sort e índice
O operador $sort pode usar um índice quando for o primeiro estágio em um pipeline ou for precedido apenas por um estágio $match.
Ao usar $sort em um cluster, cada shard ordena seus documentos de resultado usando um índice, quando disponível. Em seguida, mongos ou um dos fragmentos executa uma ordenação de mesclagem transmitida.
Exemplos
Os exemplos nesta página usam dados do conjunto de dados sample_mflix. Para obter detalhes sobre como carregar este conjunto de dados em sua implantação do MongoDB autogerenciado, consulte Carregar o conjunto de dados de amostra. Se você fez alguma modificação nos bancos de dados de amostra, talvez seja necessário descartar e recriar os bancos de dados para executar os exemplos nesta página.
Ordem crescente e decrescente
Para cada campo de classificação, defina o valor como 1 para ascendente ou -1 para descendente. Por exemplo:
db.movies.aggregate( [ { $sort: { year: -1, title: 1 } }, { $limit: 5 } ])Esta operação classifica os documentos na coleção movies em ordem decrescente por year, e depois em ordem crescente por title, e retorna os cinco primeiros resultados.
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
Código JavaScript
JavaScript code with scope
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 sistemas autogerenciados (não Atlas). Para dados hospedados no MongoDB, o MongoDB também oferece uma solução de query de texto completo aprimorada, MongoDB Search.
O exemplo a seguir usa a coleção movies no conjunto de dados de amostra sample_mflix. Antes de executá-lo, crie um índice de texto no campo plot:
db.movies.createIndex( { plot: "text" } )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.movies.aggregate( [ { $match: { $text: { $search: "pirate" } } }, { $sort: { score: { $meta: "textScore" }, year: -1 } }, { $limit: 5 } ])Esta operação corresponde a documentos com $text, depois ordena de forma decrescente por metadados "textScore" e por year, e retorna os cinco primeiros resultados. O nome do campo score no documento de ordenação é ignorado pelo sistema de query. A projeção não inclui os metadados "textScore" e não retorna os metadados como parte dos documentos correspondentes. Consulte $meta para mais informações.
Os exemplos de C# nesta página utilizam o banco de dados sample_mflix a partir dos conjuntos de dados de amostra do Atlas. Para saber como criar um cluster MongoDB Atlas gratuito e carregar os conjuntos de dados de exemplo, consulte Introdução na documentação do driver MongoDB .NET/C#.
A seguinte classe Movie modela os documentos na collection sample_mflix.movies:
[BsonIgnoreExtraElements]public class Movie{ [BsonId] public ObjectId Id { get; set; } [BsonElement("title")] public string Title { get; set; } = null!; [BsonElement("year")] public int? Year { get; set; } [BsonElement("runtime")] public int? Runtime { get; set; } [BsonElement("rated")] public string? Rated { get; set; } [BsonElement("metacritic")] public int Metacritic { get; set; } [BsonElement("plot")] public string? Plot { get; set; } [BsonElement("type")] public string? Type { get; set; } [BsonElement("cast")] public string[]? Cast { get; set; } [BsonElement("directors")] public string[]? Directors { get; set; } [BsonElement("writers")] public string[]? Writers { get; set; } [BsonElement("imdb")] public ImdbData? Imdb { get; set; }}Para usar o driver MongoDB .NET/C# para adicionar um estágio $sort a uma agregação pipeline, chame o método UnionWith() em um objeto PipelineDefinition.
O exemplo a seguir cria um estágio de pipeline que primeiro filtra os documentos Movie onde Metacritic é igual a 100, em seguida, classifica os resultados em ordem decrescente pelo campo Year e em ordem crescente pelo campo Title:
var pipeline = new EmptyPipelineDefinition<Movie>() .Match(Builders<Movie>.Filter.Eq(m => m.Metacritic, 100)) .Sort(Builders<Movie>.Sort.Combine( Builders<Movie>.Sort.Descending(m => m.Year), Builders<Movie>.Sort.Ascending(m => m.Title)));Para usar o driver Node.js do MongoDB para adicionar um estágio $sort a um pipeline de agregação , use o operador $sort em um objeto de pipeline.
O exemplo a seguir cria uma etapa de pipeline que ordena os documentos de entrada movie primeiro em ordem decrescente pelo campo year e depois em ordem crescente pelo campo title. O exemplo em seguida executa o pipeline de agregação:
const pipeline = [{ $sort: { year: -1, title: 1 } }];
const cursor = collection.aggregate(pipeline);return cursor;Saiba mais
Para exemplos completos de agregação que utilizam $sort, consulte os Tutoriais completos do pipeline de agregação.