Docs 菜单

Docs 主页开发应用程序MongoDB Manual

$expr

在此页面上

  • 定义
  • 兼容性
  • 语法
  • 行为
  • 举例

5.0 版本中的更改

$expr

允许在查询语言中使用聚合表达式

可以使用 $expr 查找托管在以下环境中的部署:

  • MongoDB Atlas :用于在云中部署 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 }

某些查询需要在定义查询筛选器时执行条件逻辑的能力。聚合管道提供$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 计算出了有效的折扣价格,但该价格并没有反映在返回的文档中。相反,返回的文档展示了原始状态下的匹配文档。查找操作没有返回 binderlegal pad 文档,因为其折扣价格大于 5

← 评估查询操作符