$addFields / $set în MongoDB & NoSQL

Agregare & Analytics MongoDB 3.4

Etapa $addFields (alias $set) adaugă câmpuri calculate sau suprascrie câmpuri existente, păstrând restul documentului.

Sintaxă
{ $addFields: { <camp>: <expresie>, ... } }
{ $set: { <camp>: <expresie>, ... } }

Ce face $addFields / $set

$addFields (MongoDB 3.4+) adaugă câmpuri noi la fiecare document fără să-ți ceară să enumeri câmpurile existente, cum face $project. Dacă un câmp există deja, este înlocuit cu valoarea calculată.

$set (MongoDB 4.2+) este un alias, cu același efect. Ambele pot fi folosite și în actualizările cu pipeline: updateMany({}, [{ $set: { nrProduse: { $size: '$produse' } } }]) salvează câmpul calculat în documente.

Parametri

Parametru Descriere
camp: expresie Câmpul nou sau suprascris și expresia lui.

Ce returnează

Documentele complete, cu câmpurile adăugate.

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: Număr de produse și comandă mare

Câmpurile noi apar la final; $project ascunde câteva câmpuri, ca rezultatul să fie scurt.

db.comenzi.aggregate([{ $addFields: { nrProduse: { $size: '$produse' }, mare: { $gte: ['$total', 100] } } }, { $project: { produse: 0, oras: 0, status: 0 } }])

Ieșire în mongosh

[
  { _id: 1, client: 'Ana', total: 120, nrProduse: 2, mare: true },
  { _id: 2, client: 'Dan', total: 85, nrProduse: 1, mare: false },
  { _id: 3, client: 'Ioana', total: 240, nrProduse: 3, mare: true },
  { _id: 4, client: 'Mihai', total: 60, nrProduse: 0, mare: false }
]

Exemplul 2: $set: suprascrierea unui câmp

Totalul crește cu costul livrării, iar livrare.cost creează un subdocument.

db.comenzi.aggregate([{ $match: { _id: 2 } }, { $set: { total: { $add: ['$total', 15] }, 'livrare.cost': 15 } }])

Ieșire în mongosh

[
  {
    _id: 2,
    client: 'Dan',
    oras: 'Cluj',
    total: 100,
    status: 'noua',
    produse: [ 'carte' ],
    livrare: { cost: 15 }
  }
]

Greșeli frecvente

  • Etapa $set din agregare nu modifică datele din colecție; doar rezultatul. Pentru salvare folosește-o într-un update cu pipeline sau pune $merge la final.
  • Nu confunda etapa $set cu operatorul de update $set: în etapă valorile sunt expresii ('$total' înseamnă câmpul), în update sunt valori literale.

Comenzi înrudite

  • $project: Etapa $project alege, redenumește sau calculează câmpurile documentelor care merg mai departe în pipeline.
  • $out / $merge: Etapele $out și $merge salvează rezultatul unei agregări într-o colecție: $out o înlocuiește complet, $merge o actualizează.
  • $expr: Operatorul $expr permite expresii de agregare în find(), de exemplu compararea a două câmpuri din același document.