Página inicial do Docs → Desenvolver aplicações → Manual do MongoDB
$expr
Definição
Alterado na versão 5.0.
$expr
Permite o uso de expressões de aggregation dentro da linguagem de query.
Compatibilidade
Você pode utilizar o $expr
para implantações hospedadas nos seguintes ambientes:
MongoDB Atlas: o serviço totalmente gerenciado para implantações MongoDB na nuvem
MongoDB Enterprise: a versão autogerenciada e baseada em assinatura do MongoDB
MongoDB Community: uma versão código-disponível, de uso gratuito e autogerenciada do MongoDB
Sintaxe
$expr
tem a seguinte sintaxe:
{ $expr: { <expression> } }
Os parâmetros podem ser qualquer expressão de aggregation válida. Para obter mais informações, consulte Operadores de expressão.
Comportamento
$expr
pode criar expressões de query que comparam campos do mesmo documento em um estágio $match
.
Se o estágio $match
fizer parte de um estágio $lookup
, $expr
poderá comparar campos usando variáveis let
. Consulte Realizar várias uniões e uma subquery correlacionada com $lookup
para obter um exemplo.
Os operadores de comparação $eq
, $lt
, $lte
, $gt
e $gte
colocados em um operador $expr
podem utilizar um índice na collection from
referenciada em um estágio $lookup
. Limitações:
Índices multichave não são usados.
Os índices não são usados para comparações onde o operando é um array ou o tipo de operando é indefinido.
Os índices não são usados para comparações com mais de um operando de caminho do campo.
Exemplos
Comparar dois campos de um único documento
Considere uma collection monthlyBudget
com os seguintes documentos:
db.monthlyBudget.insertMany( [ { _id : 1, category : "food", budget : 400, spent : 450 }, { _id : 2, category : "drinks", budget : 100, spent : 150 }, { _id : 3, category : "clothes", budget : 100, spent : 50 }, { _id : 4, category : "misc", budget : 500, spent : 300 }, { _id : 5, category : "travel", budget : 200, spent : 650 } ] )
A operação a seguir usa $expr
para localizar documentos em que o valor spent
excede budget
:
db.monthlyBudget.find( { $expr: { $gt: [ $spent , $budget ] } } )
A operação retorna os seguintes resultados:
{ _id : 1, category : "food", budget : 400, spent : 450 } { _id : 2, category : "drinks", budget : 100, spent : 150 } { _id : 5, category : "travel", budget : 200, spent : 650 }
Usando $expr
com declarações condicionais
Algumas queries exigem a capacidade de executar lógica condicional ao definir um filtro de query. O aggregation pipeline fornece ao operador $cond
para expressar instruções condicionais. Usando $expr
com o operador $cond
, você pode especificar um filtro condicional para sua declaração de query.
Criar uma coleção supplies
de amostra com os seguintes documentos:
db.supplies.insertMany( [ { _id : 1, item : "binder", qty : NumberInt("100"), price : NumberDecimal("12") }, { _id : 2, item : "notebook", qty : NumberInt("200"), price : NumberDecimal("8") }, { _id : 3, item : "pencil", qty : NumberInt("50"), price : NumberDecimal("6") }, { _id : 4, item : "eraser", qty : NumberInt("150"), price : NumberDecimal("3") }, { _id : 5, item : "legal pad", qty : NumberInt("42"), price : NumberDecimal("10") } ] )
Suponha que, para uma futura venda no próximo mês, você queira descontar os preços de forma que:
Se
qty
for maior ou igual a 100, o preço com desconto seja 0,5 doprice
.Se
qty
for inferior a 100, o preço com desconto seja 0,75 doprice
.
Antes de aplicar os descontos, você gostaria de saber quais itens da collection supplies
têm um preço com desconto inferior a 5
.
O exemplo a seguir usa $expr
com $cond
para calcular o preço com desconto com base em qty
e $lt
para retornar documentos cujo preço de desconto calculado é menor que NumberDecimal("5")
:
// Aggregation expression to calculate discounted price let discountedPrice = { $cond: { if: { $gte: ["$qty", 100] }, then: { $multiply: ["$price", NumberDecimal("0.50")] }, else: { $multiply: ["$price", NumberDecimal("0.75")] } } }; // Query the supplies collection using the aggregation expression db.supplies.find( { $expr: { $lt:[ discountedPrice, NumberDecimal("5") ] } });
A tabela a seguir mostra o preço com desconto para cada documento e se o preço com desconto é inferior a NumberDecimal("5")
(ou seja, se o documento atende à condição de query).
Documento | Preço com desconto | < NumberDecimal("5") |
---|---|---|
{"_id": 1, "item": "binder", "qty": 100, "price": NumberDecimal("12") } | NumberDecimal("6,00") | false |
{"_id": 2, "item": "notebook", "qty": 200, "price": NumberDecimal("8") } | NumberDecimal("4,00") | true |
{"_id": 3, "item": "pencil", "qty": 50, "price": NumberDecimal("6") } | NumberDecimal("4,50") | true |
{"_id": 4, "item": "eraser", "qty": 150, "price": NumberDecimal("3") } | NumberDecimal("1,50") | true |
{"_id": 5, "item": "legal pad", "qty": 42, "price": NumberDecimal("10") } | NumberDecimal("7,50") | false |
A operação db.collection.find()
retorna os documentos cujo preço com desconto calculado é menor que NumberDecimal("5")
:
{ _id : 2, item : "notebook", qty : 200 , price : NumberDecimal("8") } { _id : 3, item : "pencil", qty : 50 , price : NumberDecimal("6") } { _id : 4, item : "eraser", qty : 150 , price : NumberDecimal("3") }
Embora $cond
calcule um preço com desconto efetivo, esse preço não é refletido nos documentos retornados. Em vez disso, os documentos retornados representam os documentos correspondentes em seu estado original. A operação de busca não retornou os documentos binder
ou legal pad
, pois o preço com desconto era maior que 5
.