$expr

在本页面

Definition

3.6 版的新功能。

  • $expr
    • 允许在查询语言中使用聚合表达式。

$expr具有以下语法:

{ $expr: { <expression> } }

参数可以是任何有效的expression。有关表达式的更多信息,请参见Expressions

Behavior

$expr可以构建查询表达式,以在$match阶段比较同一文档中的字段。

如果$match阶段是$lookup阶段的一部分,则$expr可以使用let变量比较字段。有关示例,请参见使用$ lookup 指定多个联接条件

Examples

比较单个文档中的两个字段

考虑包含以下文档的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 }

以下操作使用$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 }

将$ expr 与条件语句一起使用

在定义查询过滤器时,某些查询需要能够执行条件逻辑。聚合框架提供cond运算符,用于将条件逻辑应用于流水线阶段。您可以将$expr$cond运算符结合使用,以根据对源数据的条件修改进行查询。

考虑包含以下文档的supplies集合。 supplies集合中的每个文档都代表一个项目,其数量和价格:

{ "_id" : 1, "item" : "binder", "qty" : 100 , "price" : 12 }
{ "_id" : 2, "item" : "notebook", "qty" : 200 , "price" : 8 }
{ "_id" : 3, "item" : "pencil", "qty" : 50 , "price" : 6 }
{ "_id" : 4, "item" : "eraser", "qty" : 150 , "price" : 3 }
{ "_id" : 5, "item" : "legal pad", "qty" : 42 , "price" : 10}

应用程序会自动对数量大于100的任何商品的价格应用50%折扣。否则,应用程序将对价格施加25%折扣。

用户需要知道supplies集合中的哪些项目的折扣价低于5。用户编写一个查询,该查询:

  • 使用条件逻辑来确定适用于给定文档的折扣。

  • 计算该文件的折扣价。

  • 仅返回折扣价小于5的文档。

该查询仅返回打折价格低于5supplies集合中的文档。

以下操作使用$expr运算符访问cond$lt聚合运算符实现了前面的步骤:

db.supplies.find( {
    $expr: {
       $lt:[ {
          $cond: {
             if: { $gte: ["$qty", 100] },
             then: { $multiply: ["$price", 0.50] },
             else: { $multiply: ["$price", 0.75] }
           }
       },
       5 ] }
} )
  • $cond根据qty的值修改 Importing 文档。具体来说,它使用$gte比较qty并使用$multiply修改价格。

  • 文档_id : 1qty为 100.$cond返回将price乘以0.50的结果,有效地应用50%折扣,得到6的值。

    • 文档id : 3qty50$cond返回将price0.75相乘的结果,有效地应用25%折扣,得到4的值。
  • $lt将返回值与提供的值5进行比较。

  • 文档_id : 1cond返回6。由于$lt [6, 5]的计算结果为 false,因此表达式不返回文档。

    • 文档_id : 3cond返回4。由于$lt [4, 5]的计算结果为 true,因此表达式返回文档。

find()continue 将$cond应用于supplies集合中的每个文档。该操作返回以下结果:

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

$cond修改 Importing 文档作为查询过滤的一部分,但不将修改持久化到磁盘上。结果代表匹配文档的原始状态。查找操作未返回binderlegal pad文档,因为它们的修改价格大于5。特别:

  • binder的数量为200$cond逻辑应用.75乘法器,该乘法器解析为6。由于6大于5,因此find()过滤出binder文档。

  • legal pad的数量为42$cond逻辑应用.50乘法器,该乘法器解析为5。由于该操作使用$lt运算符,因此修改后的价格不低于5,并且find()过滤出legal pad文档。