$expr

On this page本页内容

Definition定义

New in version 3.6.版本3.6中的新功能。

$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行为

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与条件语句一起使用

Some queries require the ability to execute conditional logic when defining a query filter. 在定义查询筛选器时,有些查询需要能够执行条件逻辑。The aggregation framework 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 the price.如果qty大于或等于100,则折扣价格为价格的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 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")(即单据是否满足查询条件)。

Document文档Discounted Price折扣价< 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.查找操作没有返回binderlegal pad文档,因为它们的折扣价格大于5