Database Manual / Reference / Query Language / Query Predicates / Miscellaneous

$expr

Definition定义

Changed in version 5.0.在版本5.0中的更改。

$expr
Allows the use of expressions within a query predicate.允许在查询谓词中使用表达式

Compatibility兼容性

You can use $expr for deployments hosted in the following environments:您可以将$expr用于在以下环境中托管的部署:

  • MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud:云中MongoDB部署的完全托管服务
  • MongoDB Enterprise: The subscription-based, self-managed version of MongoDB:MongoDB的基于订阅的自我管理版本
  • MongoDB Community: The source-available, free-to-use, and self-managed version of MongoDB:MongoDB的源代码可用、免费使用和自我管理版本

Syntax语法

{ $expr: { <expression> } }

The argument can be any valid expression.参数可以是任何有效的表达式。

Behavior行为

$expr in $lookup Operations$lookup操作中的$expr

When $expr appears in a $match stage that is part of a $lookup subpipeline, $expr can refer to let variables defined by the $lookup stage. For an example, see Use Multiple Join Conditions and a Correlated Subquery.$expr出现在$lookup子管道的$match阶段时,$expr可以引用由$lookup阶段定义的let变量。例如,请参阅使用多个联接条件和相关子查询。

The $eq, $lt, $lte, $gt, and $gte comparison operators placed in an $expr operator can use an index on the from collection referenced in a $lookup stage. Limitations:放置在$expr运算符中的$eq$lt$lte$gt$gte比较运算符可以在$lookup阶段引用的from集合上使用索引。限制:

  • Indexes can only be used for comparisons between fields and constants, so the let operand must resolve to a constant.索引只能用于字段和常量之间的比较,因此let操作数必须解析为常量。

    For example, a comparison between $a and a constant value can use an index, but a comparison between $a and $b cannot.例如,$a和常量值之间的比较可以使用索引,但$a$b之间的比较不能。

  • Indexes are not used for comparisons where the let operand resolves to an empty or missing value.let操作数解析为null值或缺失值时,索引不用于比较。
  • Multikey indexes are not used.不使用多键索引

Examples示例

Compare Two Fields from a Single Document比较单个文档中的两个字段

$expr can contain expressions that compare fields from the same document.$expr可以包含比较同一文档中字段的表达式。

Create a monthlyBudget collection with these documents:使用以下文档创建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 }
] )

The following operation uses $expr to find documents where the spent amount exceeds the budget:以下操作使用$expr查找spent(支出)金额超过budget(预算)的文档:

db.monthlyBudget.find( { $expr: { $gt: [ "$spent" , "$budget" ] } } )

Output:输出:

{ _id : 1, category : "food", budget : 400, spent : 450 }
{ _id : 2, category : "drinks", budget : 100, spent : 150 }
{ _id : 5, category : "travel", budget : 200, spent : 650 }

Use $expr With Conditional Statements$expr与条件语句一起使用

Some queries require the ability to execute conditional logic when defining a query filter. The aggregation pipeline provides the $cond operator to express conditional statements. 在定义查询筛选器时,某些查询需要执行条件逻辑的能力。聚合管道提供$cond运算符来表示条件语句。By using $expr with the $cond operator, you can specify a conditional filter for your query statement.通过使用$expr$cond运算符,您可以为查询语句指定条件筛选器。

Create a sample supplies collection with the following documents:使用以下文档创建示例supplies集合:

db.supplies.insertMany( [
{ _id : 1, item : "binder", qty : Int32("100"), price : Decimal128("12") },
{ _id : 2, item : "notebook", qty : Int32("200"), price : Decimal128("8") },
{ _id : 3, item : "pencil", qty : Int32("50"), price : Decimal128("6") },
{ _id : 4, item : "eraser", qty : Int32("150"), price : Decimal128("3") },
{ _id : 5, item : "legal pad", qty : Int32("42"), price : Decimal128("10") }
] )

Assume that for an upcoming sale next month, you want to discount the prices such that:假设下个月即将到来的促销活动,您想折扣价格,以便:

  • If qty is greater than or equal to 100, the discounted price will be 0.5 of the price.如果qty大于或等于100,折扣价为price的0.5。
  • If qty is less than 100, the discounted price is 0.75 of the price.如果qty少于100,折扣价为price的0.75。

Before applying the discounts, you would like to know which items in the supplies collection have a discounted price of less than 5.在申请折扣之前,您想知道supplies集合中哪些商品的折扣价格低于5

The following example uses $expr with $cond to calculate the discounted price based on the qty and $lt to return documents whose calculated discount price is less than Decimal128("5"):以下示例使用$expr$cond根据数量计算折扣价,使用$lt返回计算出的折扣价小于Decimal128("5")的文档:

// Aggregation expression to calculate discounted price计算折扣价格的聚合表达式

let discountedPrice = {
$cond: {
if: { $gte: ["$qty", 100] },
then: { $multiply: ["$price", Decimal128("0.50")] },
else: { $multiply: ["$price", Decimal128("0.75")] }
}
};

// Query the supplies collection using the aggregation expression使用聚合表达式查询供应品集合

db.supplies.find( { $expr: { $lt:[ discountedPrice, Decimal128("5") ] } });

The following table shows the discounted price for each document and whether discounted price is less than Decimal128("5") (i.e. whether the document meets the query condition).下表显示了每个文档的折扣价格以及折扣价格是否小于Decimal128("5")(即文档是否符合查询条件)。

Document文档Discounted Price折扣价< Decimal128("5")
{"_id": 1, "item": "binder", "qty": 100, "price": Decimal128("12") }Decimal128("6.00")false
{"_id": 2, "item": "notebook", "qty": 200, "price": Decimal128("8") }Decimal128("4.00")true
{"_id": 3, "item": "pencil", "qty": 50, "price": Decimal128("6") }Decimal128("4.50")true
{"_id": 4, "item": "eraser", "qty": 150, "price": Decimal128("3") }Decimal128("1.50")true
{"_id": 5, "item": "legal pad", "qty": 42, "price": Decimal128("10") }Decimal128("7.50")false

The db.collection.find() operation returns the documents whose calculated discount price is less than Decimal128("5"):db.collection.find()操作返回计算出的折扣价格小于Decimal128("5")的文档:

{ _id : 2, item : "notebook", qty : 200 , price : Decimal128("8") }
{ _id : 3, item : "pencil", qty : 50 , price : Decimal128("6") }
{ _id : 4, item : "eraser", qty : 150 , price : Decimal128("3") }

Even though $cond calculates an effective discounted price, that price is not reflected in the returned documents. 即使$cond计算了一个有效的折扣价格,该价格也不会反映在返回的文档中。Instead, the returned documents represent the matching documents in their original state. 相反,返回的文档表示处于原始状态的匹配文档。The find operation did not return the binder or legal pad documents, as their discounted price was greater than 5.查找操作没有返回binder(活页夹)或legal pad(法律文件),因为它们的折扣价大于5