Docs 主页 → 开发应用程序 → MongoDB Manual
$expr
定义
5.0 版本中的更改。
$expr
允许在查询语言中使用聚合表达式。
兼容性
可以使用 $expr
查找托管在以下环境中的部署:
MongoDB Atlas :用于在云中部署 MongoDB 的完全托管服务
MongoDB Enterprise:基于订阅、自我管理的 MongoDB 版本
MongoDB Community:源代码可用、免费使用且可自行管理的 MongoDB 版本
语法
$expr
通过以下语法实现:
{ $expr: { <expression> } }
行为
$expr
可以构建查询表达式,用于在$match
阶段比较同一文档中的字段。
如果$match
阶段是$lookup
阶段的一部分,则$expr
可以使用let
变量比较字段。有关示例,请参阅使用$lookup
执行多个连接和关联子查询。
位于 $eq
$expr
操作符中的 、$lt
$gte
、$lte
、$gt
和 比较操作符可以使用from
$lookup
阶段中引用的 集合上的索引。限制:
举例
比较同一文档中的两个字段
请考虑包含以下文档的 monthlyBudget
集合:
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 } ] )
以下操作使用$expr
查找spent
金额超过budget
的文档:
db.monthlyBudget.find( { $expr: { $gt: [ $spent , $budget ] } } )
操作返回以下结果:
{ _id : 1, category : "food", budget : 400, spent : 450 } { _id : 2, category : "drinks", budget : 100, spent : 150 } { _id : 5, category : "travel", budget : 200, spent : 650 }
将$expr
与条件语句结合使用
某些查询需要在定义查询筛选器时执行条件逻辑的能力。聚合管道提供$cond
操作符来表达条件语句。通过将$expr
与$cond
操作符一起使用,您可以为查询语句指定条件筛选器。
使用以下文档创建示例 supplies
集合:
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") } ] )
假设在下个月即将举行的促销活动中,您想提供价格折扣:
如果
qty
大于或等于 100,折扣价格将为price
的 0.5。如果
qty
小于 100,折扣价就是price
的 0.75。
在应用折扣之前,您想知道 supplies
集合中哪些商品的折扣价格低于 5
。
以下示例使用$expr
和$cond
根据qty
和$lt
计算折扣价格,以返回计算出的折扣价格小于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") ] } });
下表显示了每个文档的折扣价格以及折扣价格是否小于 NumberDecimal("5")
(即文档是否满足查询条件)。
文档 | 折扣价格 | < 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 |
db.collection.find()
操作返回计算出的折扣价低于 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") }
尽管 $cond
计算出了有效的折扣价格,但该价格并没有反映在返回的文档中。相反,返回的文档展示了原始状态下的匹配文档。查找操作没有返回 binder
或 legal pad
文档,因为其折扣价格大于 5
。