$expr în MongoDB & NoSQL

Operatorul $expr permite expresii de agregare în find(), de exemplu compararea a două câmpuri din același document.

Sintaxă
{ $expr: { <expresie de agregare> } }

Ce face $expr

Filtrele obișnuite compară un câmp cu o valoare fixă. $expr (MongoDB 3.6+) acceptă expresii de agregare, în care '$stoc' înseamnă valoarea câmpului stoc. Astfel poți compara două câmpuri între ele sau poți filtra după un calcul (lungimea unui tablou, o sumă, o dată).

Operatorii de comparare din $expr au forma de agregare, cu un tablou de două valori: { $lt: ['$stoc', '$stocMinim'] }. Același operator se folosește și în $match sau în $lookup cu pipeline.

Parametri

Parametru Descriere
expresie Orice expresie de agregare care întoarce adevărat sau fals.

Ce returnează

Un cursor cu documentele pentru care expresia este adevărată.

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: [] }
])
db.produse.insertMany([
  { _id: 'caiet', stoc: 40, stocMinim: 50 },
  { _id: 'pix', stoc: 120, stocMinim: 30 },
  { _id: 'rucsac', stoc: 5, stocMinim: 5 }
])

Exemplul 1: Produse sub stocul minim

Se compară două câmpuri ale aceluiași document; rucsacul are stocul egal cu minimul, deci nu apare.

db.produse.find({ $expr: { $lt: ['$stoc', '$stocMinim'] } })

Ieșire în mongosh

[ { _id: 'caiet', stoc: 40, stocMinim: 50 } ]

Exemplul 2: Comenzi cu cel puțin două produse

Operatorul de agregare $size calculează lungimea tabloului.

db.comenzi.find({ $expr: { $gte: [{ $size: '$produse' }, 2] } }, { client: 1 })

Ieșire în mongosh

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

Greșeli frecvente

  • Fără $ în față, 'stoc' este textul „stoc”, nu valoarea câmpului.
  • În $expr, operatorul de agregare $size dă eroare dacă un document nu are tabloul; protejează-te cu { $ifNull: ['$produse', []] }.
  • $expr poate folosi indexuri doar pentru comparații simple de egalitate și interval cu valori fixe; comparațiile între câmpuri scanează documentele.

Comenzi înrudite

  • $match: Etapa $match păstrează în pipeline doar documentele care se potrivesc filtrului, cu aceeași sintaxă ca find().
  • $size: Operatorul $size găsește documentele în care un tablou are exact numărul dat de elemente.
  • $addFields / $set: Etapa $addFields (alias $set) adaugă câmpuri calculate sau suprascrie câmpuri existente, păstrând restul documentului.