$sort, $limit e $skip no pipeline
Você ordenará e paginará os resultados de agregação e entenderá as regras do otimizador para mover $match e $sort para antes de $group.
$sort, $limit e $skip no pipeline é uma aula grátis de MongoDB Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de MongoDB Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de MongoDB Academy inclui 4 aulas no total.
Visão geral: ordenação e paginação de resultados
Três estágios do pipeline de agregação controlam a ordem e o volume dos resultados: $sort ordena os documentos por um ou mais campos, $limit mantém apenas os primeiros N documentos e $skip descarta os primeiros N documentos. Juntos, eles implementam ordenação e paginação. Entender onde colocá-los no pipeline tem um impacto significativo no desempenho.
O estágio $sort
O estágio $sort ordena os documentos pelos valores de um ou mais campos. Use 1 para ordem crescente e -1 para ordem decrescente. Quando vários campos são especificados, os documentos são ordenados primeiro pelo primeiro campo, depois pelo segundo campo entre os que estão empatados, e assim por diante — exatamente como na ordenação por várias chaves do SQL ou em find().sort() do MongoDB.
// Sort by revenue descending, then alphabetically by name for ties
db.products.aggregate([
{ $group: { _id: '$category', revenue: { $sum: '$price' } } },
{ $sort: { revenue: -1, _id: 1 } } // revenue desc, category name asc
]);$sort e uso de índices
Quando $sort é o primeiro estágio do pipeline (ou vem depois de um $match que usa um índice), o MongoDB pode usar um índice para realizar a ordenação, evitando completamente uma ordenação em memória. Quando $sort aparece depois de estágios que produzem novos campos, como $group ou $project, nenhum índice está disponível e o MongoDB realiza uma ordenação em memória. Ordenações em memória grandes (>100 MB) exigem allowDiskUse: true.
// Index-backed sort: $sort on indexed field before any transformation
db.orders.aggregate([
{ $match: { userId: 'u1' } },
{ $sort: { createdAt: -1 } } // if createdAt is indexed, no in-memory sort
]);
// In-memory sort: $sort after $group (computed field, no index)
db.orders.aggregate([
{ $group: { _id: '$userId', total: { $sum: '$amount' } } },
{ $sort: { total: -1 } } // in-memory: 'total' is a computed field
]);O estágio $limit
$limit encaminha apenas os primeiros N documentos e descarta os demais. É simples: passe um número inteiro que especifique o número máximo de documentos permitidos. Colocar $limit antes de estágios dispendiosos, como $lookup, reduz significativamente o número de junções ou consultas realizadas. Pergunte sempre: “Posso limitar antecipadamente?”
// Top 10 best-selling products
db.orders.aggregate([
{ $group: { _id: '$productId', sold: { $sum: '$qty' } } },
{ $sort: { sold: -1 } },
{ $limit: 10 }, // only top 10 pass through
// Only 10 lookups instead of thousands:
{ $lookup: { from: 'products', localField: '_id', foreignField: '_id', as: 'product' } }
]);O estágio $skip
$skip descarta os primeiros N documentos do fluxo. Ele é o equivalente, na agregação, à paginação por deslocamento: a página 2 começa com skip 10 (considerando um limite de 10 por página). $skip deve sempre vir depois de $sort para produzir resultados consistentes — ignorar documentos não ordenados gera páginas imprevisíveis. Assim como OFFSET no SQL, $skip é lento com deslocamentos grandes, pois o MongoDB ainda precisa processar todos os documentos ignorados.
const PAGE = 2;
const PAGE_SIZE = 10;
db.articles.aggregate([
{ $match: { status: 'published' } },
{ $sort: { publishedAt: -1 } },
{ $skip: (PAGE - 1) * PAGE_SIZE }, // skip page 1's 10 docs
{ $limit: PAGE_SIZE } // take page 2's 10 docs
]);Otimizador: combinação de $sort + $limit
O otimizador de agregação do MongoDB detecta quando um estágio $sort é seguido imediatamente por um estágio $limit e combina os dois em uma ordenação dos N primeiros. Em vez de ordenar todos os documentos e depois descartar a maioria, o MongoDB mantém apenas os N principais candidatos em uma fila de prioridade durante a ordenação, usando memória O(N) em vez de memória O(total). Essa otimização é automática: basta escrever $sort seguido de $limit.
// This pattern triggers the top-N sort optimisation
db.reviews.aggregate([
{ $match: { productId: 'p1' } },
{ $sort: { rating: -1, helpful: -1 } }, // sort
{ $limit: 5 } // $sort + $limit merged into top-5 sort internally
]);
// MongoDB never sorts ALL reviews; it tracks only the best 5Otimizador: reordenação de $match e $sort
O otimizador de agregação também move automaticamente um estágio $match para uma posição anterior no pipeline quando isso é seguro. Por exemplo, se $sort aparecer antes de $match em um campo que $sort não calculou, o otimizador move $match para antes de $sort, reduzindo o número de documentos que precisam ser ordenados. Você pode observar as alterações do otimizador na saída de explain().
// You write:
db.orders.aggregate([
{ $sort: { amount: -1 } },
{ $match: { status: 'completed' } } // optimizer moves this BEFORE $sort
]);
// Optimized execution (equivalent to):
db.orders.aggregate([
{ $match: { status: 'completed' } }, // fewer docs to sort
{ $sort: { amount: -1 } }
]);Combinando os quatro: um endpoint completo de listagem
Um endpoint de API realista que lista produtos com filtros, ordenação e paginação combina $match, $sort, $skip e $limit na ordem correta. O padrão é sempre: filtrar → ordenar → ignorar → limitar. Essa ordem garante que o MongoDB use índices tanto para a filtragem quanto, quando possível, para a ordenação antes de descartar documentos desnecessários.
async function getProducts({ category, sort = 'price', page = 1, pageSize = 20 }) {
return db.products.aggregate([
{ $match: { category, inStock: true } }, // 1. filter
{ $sort: { [sort]: 1 } }, // 2. sort
{ $skip: (page - 1) * pageSize }, // 3. offset
{ $limit: pageSize } // 4. take page
]).toArray();
}Desempenho de $skip em deslocamentos profundos
O problema fundamental de $skip é que o MongoDB ainda precisa processar e descartar todos os documentos ignorados. Na página 1000, com 20 itens por página, o MongoDB descarta 19.980 documentos antes de retornar 20. Isso fica progressivamente mais lento em páginas mais profundas. Para APIs públicas de pesquisa ou feed, nas quais os usuários raramente vão além da página 5 ou 10, a paginação por deslocamento é adequada. Para paginação profunda de alta frequência, é necessário usar paginação por conjunto de chaves.
// Page 1000 is SLOW: MongoDB processes and discards 19,980 docs
db.posts.aggregate([
{ $sort: { createdAt: -1 } },
{ $skip: 19980 }, // 999 * 20
{ $limit: 20 }
]);
// Keyset pagination: always fast regardless of page depth
db.posts.aggregate([
{ $match: { createdAt: { $lt: lastSeenTimestamp } } }, // cursor
{ $sort: { createdAt: -1 } },
{ $limit: 20 }
]);Limite de memória de $sort e allowDiskUse
Um $sort em memória no pipeline de agregação é limitado, por padrão, a 100 MB. Se a ordenação exceder esse limite, o pipeline falhará com um erro QueryExceededMemoryLimitNoDiskUseAllowed. Passe { allowDiskUse: true } como segundo argumento de aggregate() para permitir a transferência de dados excedentes para o disco. Como alternativa, aplique um $match antecipado ou use um índice de suporte para reduzir o tamanho da entrada da ordenação.
// Enable disk use for large sorts
db.events.aggregate(
[
{ $match: { year: 2024 } },
{ $sort: { timestamp: -1 } },
{ $group: { _id: '$userId', events: { $push: '$type' } } }
],
{ allowDiskUse: true } // allows spilling to disk
);Obtendo a contagem total junto com os resultados
Um padrão comum de API é retornar os resultados paginados e a contagem total em uma única ida e volta ao banco de dados. Use $facet para dividir o pipeline em dois ramos paralelos: um para os resultados de $skip/$limit e outro para $count. Isso evita duas chamadas de agregação separadas e é mais eficiente do que contar todos os documentos separadamente.
db.products.aggregate([
{ $match: { category: 'electronics' } },
{ $sort: { price: 1 } },
{ $facet: {
// Branch 1: paginated results
data: [
{ $skip: 0 },
{ $limit: 20 }
],
// Branch 2: total count
total: [
{ $count: 'count' }
]
}}
]);
// Output: { data: [...20 docs...], total: [{ count: 348 }] }Verificação rápida
Teste sua compreensão sobre $sort, $limit e $skip no pipeline de agregação.
Recapitulação da lição
Nesta lição, você aprendeu que: $sort ordena os documentos e se beneficia do uso de índices quando colocado no início; $limit mantém os primeiros N documentos e se combina com $sort em uma ordenação eficiente dos N primeiros; e $skip implementa a paginação por deslocamento, mas perde desempenho em deslocamentos profundos. A seguir, exploraremos estágios avançados de agregação, incluindo $lookup para unir coleções.
Aprenda JavaScript com um tutor de IA — grátis
Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.
- Cursos
- 30
- Aulas
- 120
Perguntas Frequentes
A aula “$sort, $limit e $skip no pipeline” é grátis?
Sim — o texto completo de “$sort, $limit e $skip no pipeline” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de MongoDB Academy, atualize para CoddyKit PRO. O curso de MongoDB Academy inclui 4 aulas no total.
O que vou aprender em “$sort, $limit e $skip no pipeline”?
Você ordenará e paginará os resultados de agregação e entenderá as regras do otimizador para mover $match e $sort para antes de $group. Você pratica MongoDB Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar MongoDB Academy?
Nenhuma experiência prévia é necessária. MongoDB Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “$sort, $limit e $skip no pipeline”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de MongoDB Academy?
Sim. Cada aula de MongoDB Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Conceitos de pipeline: etapas, operadores e expressões
- $match e $project: filtrando e remodelando
- $group: agregando e calculando totais
- $sort, $limit e $skip no pipeline