$expr
On this page
Definition定义
Changed in version 5.0.
$expr
-
Allows the use of aggregation expressions within the query language.允许在查询语言中使用聚合表达式。$expr
has the following syntax:具有以下语法:{ $expr: { <expression> } }
The arguments can be any valid aggregation expression. For more information, see Expressions.参数可以是任何有效的聚合表达式。有关详细信息,请参阅表达式。
Behavior行为
$expr
can build query expressions that compare fields from the same document in a 可以构建查询表达式来比较$match
stage.$match
阶段中同一文档中的字段。
If the 如果$match
stage is part of a $lookup
stage, $expr
can compare fields using let
variables. $match
阶段是$lookup
阶段的一部分,$expr
可以使用let
变量比较字段。See Perform Multiple Joins and a Correlated Subquery with 请参见执行多个联接和带有$lookup
for an example.$lookup
的相关子查询作为示例。
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. $expr
运算符中的$eq
、$lt
、$lte
、$gt
和$gte
比较运算符可以对$lookup
阶段中引用的from
集合使用索引。Limitations:限制:
-
Multikey indexes are not used.不使用多键索引。 -
Indexes are not used for comparisons where the operand is an array or the operand type is undefined.如果操作数是数组或操作数类型未定义,则不将索引用于比较。 -
Indexes are not used for comparisons with more than one field path operand.索引不用于与多个字段路径操作数进行比较。
Examples实例
Compare Two Fields from A Single Document比较单个文档中的两个字段
Consider an 考虑一个包含以下文档的monthlyBudget
collection with the following documents:monthlyBudget
集合:
{ "_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" ] } } )
The operation returns the following results:该操作返回以下结果:
{ "_id" : 1, "category" : "food", "budget" : 400, "spent" : 450 }
{ "_id" : 2, "category" : "drinks", "budget" : 100, "spent" : 150 }
{ "_id" : 5, "category" : "travel", "budget" : 200, "spent" : 650 }
Using $expr
With Conditional Statements将$expr
与条件语句一起使用
$expr
With Conditional StatementsSome 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" : 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") }
])
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 theprice
.qty
大于或等于100
,折扣价格将为price
的0.5
。 -
If如果qty
is 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 NumberDecimal("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") ] } });
The following table shows the discounted price for each document and whether discounted price is less than 下表显示了每张单据的折扣价,以及折扣价是否小于NumberDecimal("5")
(i.e. whether the document meets the query condition).NumberDecimal("5")
(即单据是否满足查询条件)。
< NumberDecimal("5") | ||
---|---|---|
{"_id": 1, "item": "binder", "qty": 100, "price": NumberDecimal("12") } | NumberDecimal("6.00") | false |
{"_id": 2, "item": "noteboook", "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 |
The db.collection.find()
operation returns the documents whose calculated discount price is less than NumberDecimal("5")
: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") }
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
。