$sort / $limit / $skip în MongoDB & NoSQL

Agregare & Analytics MongoDB 2.2

Etapele $sort, $skip și $limit ordonează documentele din pipeline și aleg o porțiune din ele (top N, paginare).

Sintaxă
{ $sort: { <camp>: 1 | -1, ... } }
{ $skip: <n> }
{ $limit: <n> }

Ce face $sort / $limit / $skip

$sort ordonează documentele: 1 crescător, -1 descrescător; la mai multe câmpuri, ordinea cheilor contează. $limit păstrează primele n documente, iar $skip sare peste primele n.

Un $sort urmat imediat de $limit este optimizat: serverul păstrează în memorie doar cele n documente de top. Pus la început, pe un câmp indexat, $sort poate folosi indexul. Spre deosebire de find().sort().skip().limit(), aici ordinea etapelor din tablou contează.

Parametri

Parametru Descriere
$sort Câmpurile de ordonare, cu 1 sau -1.
$skip Câte documente să sară.
$limit Câte documente să păstreze.

Ce returnează

Documentele ordonate și tăiate.

Exemple

Exemplele de pe această pagină pornesc de la datele de mai jos. Rulează mai întâi acest cod, apoi exemplul.

use magazin
db.comenzi.insertMany([
  { _id: 1, client: 'Ana', oras: 'Iași', total: 120, status: 'livrata', produse: ['caiet', 'pix'] },
  { _id: 2, client: 'Dan', oras: 'Cluj', total: 85, status: 'noua', produse: ['carte'] },
  { _id: 3, client: 'Ioana', oras: 'Iași', total: 240, status: 'livrata', produse: ['rucsac', 'caiet', 'pix'] },
  { _id: 4, client: 'Mihai', oras: 'Brașov', total: 60, status: 'anulata', produse: [] }
])

Exemplul 1: Top 2 comenzi după valoare

$sort + $limit dă un clasament.

db.comenzi.aggregate([{ $sort: { total: -1 } }, { $limit: 2 }, { $project: { client: 1, total: 1 } }])

Ieșire în mongosh

[
  { _id: 3, client: 'Ioana', total: 240 },
  { _id: 1, client: 'Ana', total: 120 }
]

Exemplul 2: Pagina a doua, câte 2 pe pagină

Ordonăm după nume, sărim peste primele 2 și luăm următoarele 2.

db.comenzi.aggregate([{ $sort: { client: 1 } }, { $skip: 2 }, { $limit: 2 }, { $project: { client: 1 } }])

Ieșire în mongosh

[ { _id: 3, client: 'Ioana' }, { _id: 4, client: 'Mihai' } ]

Greșeli frecvente

  • $limit înainte de $sort ia primele n documente în ordinea naturală și abia apoi le sortează: rezultatul nu este top-ul real.
  • La sortare după un câmp cu valori egale, ordinea între ele nu e garantată și paginarea poate repeta documente; adaugă _id ca a doua cheie de sortare.
  • $skip cu valori mari este lent (documentele sărite tot sunt citite); pentru paginare adâncă filtrează după ultima valoare văzută.

Comenzi înrudite

  • $match: Etapa $match păstrează în pipeline doar documentele care se potrivesc filtrului, cu aceeași sintaxă ca find().
  • $group: Etapa $group grupează documentele după o cheie și calculează totaluri: $sum, $avg, $min, $max, $push, $addToSet.
  • $facet: Etapa $facet rulează mai multe sub-pipeline-uri pe aceleași documente și întoarce toate rezultatele într-un singur document.