Definition定义
Changed in version 5.0.在版本5.0中的更改。
$exprAllows 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索引只能用于字段和常量之间的比较,因此letoperand must resolve to a constant.let操作数必须解析为常量。For example, a comparison between例如,$aand a constant value can use an index, but a comparison between$aand$bcannot.$a和常量值之间的比较可以使用索引,但$a和$b之间的比较不能。Indexes are not used for comparisons where the当letoperand 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如果qtyis greater than or equal to 100, the discounted price will be 0.5 of theprice.qty大于或等于100,折扣价为price的0.5。If如果qtyis less than 100, the discounted price is 0.75 of theprice.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")(即文档是否符合查询条件)。
| < 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。