Ce face $facet
$facet (MongoDB 3.4+) primește documentele o singură dată și le trimite în paralel prin mai multe pipeline-uri, fiecare cu numele lui. Rezultatul este un singur document, cu câte un tablou pentru fiecare nume.
E folosit des pentru pagini de căutare: într-o singură interogare obții rezultatele paginii curente, numărul total și filtrele laterale (câte produse pe categorie, pe interval de preț). În interiorul unui facet nu poți folosi $out, $merge sau alt $facet.
Parametri
| Parametru | Descriere |
|---|---|
nume: [ etape ] |
Câte un sub-pipeline pentru fiecare rezultat dorit. |
Ce returnează
Un singur document, cu câte un câmp tablou pentru fiecare sub-pipeline.
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: Un tablou de bord într-o singură interogare
Vânzări pe oraș, statistici generale și cea mai mare comandă, calculate din aceleași date.
db.comenzi.aggregate([
{ $facet: {
peOrase: [{ $group: { _id: '$oras', comenzi: { $sum: 1 } } }, { $sort: { comenzi: -1, _id: 1 } }],
statistici: [{ $group: { _id: null, total: { $sum: '$total' }, comenzi: { $sum: 1 } } }],
top: [{ $sort: { total: -1 } }, { $limit: 1 }, { $project: { client: 1, total: 1 } }]
} }
])
Ieșire în mongosh
[
{
peOrase: [
{ _id: 'Iași', comenzi: 2 },
{ _id: 'Brașov', comenzi: 1 },
{ _id: 'Cluj', comenzi: 1 }
],
statistici: [ { _id: null, total: 505, comenzi: 4 } ],
top: [ { _id: 3, client: 'Ioana', total: 240 } ]
}
]
Exemplul 2: Paginare cu numărul total
Pagina întâi (2 rezultate) și numărul total de comenzi livrate sau noi.
db.comenzi.aggregate([
{ $match: { status: { $in: ['livrata', 'noua'] } } },
{ $facet: {
pagina: [{ $sort: { _id: 1 } }, { $limit: 2 }, { $project: { client: 1 } }],
total: [{ $count: 'n' }]
} }
])
Ieșire în mongosh
[
{
pagina: [ { _id: 1, client: 'Ana' }, { _id: 2, client: 'Dan' } ],
total: [ { n: 3 } ]
}
]
Greșeli frecvente
- Tot rezultatul
$faceteste un singur document, deci trebuie să încapă în 16 MB; nu pune în facet tablouri foarte lungi. - Sub-pipeline-urile din
$facetnu folosesc indexuri; pune$match-ul comun înainte de$facet.
Comenzi înrudite
$bucket / $bucketAuto: Etapa $bucket grupează documentele pe intervale de valori (de exemplu de preț); $bucketAuto alege singură intervalele.$count / $sortByCount: Etapa $count numără documentele ajunse în acel punct al pipeline-ului; $sortByCount numără pe valori și ordonează descrescător.$group: Etapa $group grupează documentele după o cheie și calculează totaluri: $sum, $avg, $min, $max, $push, $addToSet.