$bucket / $bucketAuto în MongoDB & NoSQL

Agregare & Analytics MongoDB 3.4

Etapa $bucket grupează documentele pe intervale de valori (de exemplu de preț); $bucketAuto alege singură intervalele.

Sintaxă
{ $bucket: { groupBy: <expresie>, boundaries: [ <l0>, <l1>, ... ], default: <id>, output: { ... } } }
{ $bucketAuto: { groupBy: <expresie>, buckets: <n>, output: { ... } } }

Ce face $bucket / $bucketAuto

$bucket (MongoDB 3.4+) pune fiecare document într-un „găleată” după valoarea lui groupBy. boundaries dă limitele, în ordine crescătoare: intervalul este închis la stânga și deschis la dreapta ([0, 100)). _id-ul fiecărui grup este limita lui de jos. Documentele care nu intră în niciun interval merg la grupul default; fără el, primești eroare.

output definește ce se calculează pe fiecare interval, ca la $group; implicit primești doar count. $bucketAuto primește doar numărul de intervale dorit și le alege astfel încât să aibă un număr cât mai egal de documente.

Parametri

Parametru Descriere
groupBy Valoarea după care se împart documentele ('$total').
boundaries Limitele intervalelor, crescătoare.
default Grupul pentru valorile din afara intervalelor.
output Acumulatorii calculați pe interval.
buckets Numărul de intervale (la $bucketAuto).

Ce returnează

Câte un document pe interval, cu _id = limita de jos (la $bucketAuto: { min, max }).

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: Comenzi pe intervale de valoare

Sub 100 de lei, 100–199 și 200–499 de lei.

db.comenzi.aggregate([{ $bucket: { groupBy: '$total', boundaries: [0, 100, 200, 500], default: 'altele', output: { comenzi: { $sum: 1 }, clienti: { $push: '$client' } } } }])

Ieșire în mongosh

[
  { _id: 0, comenzi: 2, clienti: [ 'Dan', 'Mihai' ] },
  { _id: 100, comenzi: 1, clienti: [ 'Ana' ] },
  { _id: 200, comenzi: 1, clienti: [ 'Ioana' ] }
]

Exemplul 2: Două intervale alese automat

Cele patru valori (60, 85, 120, 240) sunt împărțite în două grupuri egale.

db.comenzi.aggregate([{ $bucketAuto: { groupBy: '$total', buckets: 2 } }])

Ieșire în mongosh

[
  { _id: { min: 60, max: 120 }, count: 2 },
  { _id: { min: 120, max: 240 }, count: 2 }
]

Greșeli frecvente

  • Fără default, o valoare în afara limitelor (de exemplu o comandă de 600 de lei) oprește agregarea cu eroare.
  • Limita de sus a fiecărui interval nu este inclusă: o comandă de exact 100 de lei intră în grupul 100, nu în 0.

Comenzi înrudite

  • $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.
  • $count / $sortByCount: Etapa $count numără documentele ajunse în acel punct al pipeline-ului; $sortByCount numără pe valori și ordonează descrescător.