$expr

在本页面

  • 定义

  • 行为

  • 例子

定义

version 3.6 中的新内容。

  • $expr

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

$expr具有以下语法:

{ $expr: { <expression> } }

arguments 可以是任何有效的表达。有关表达式的更多信息,请参阅表达式。

行为

$expr可以 build 查询表达式,用于比较$match阶段中同一文档的字段。

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

例子

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

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

使用带有条件 Statements 的$expr

某些查询需要能够在定义查询过滤器时执行条件逻辑。聚合 framework 提供了cond operator,用于将条件逻辑应用于管道阶段。您可以将$expr与$cond operator 一起使用,以根据对源数据的条件修改进行查询。

考虑带有以下文档的supplies集合。 supplies集合中的每个文档代表 item,其数量和价格:

{ "_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}

_application 会自动将50%折扣应用于数量超过100的任何 item 的价格。否则,application 会对价格应用25%折扣。

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

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

  • 计算该文件的折扣价。

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

查询仅返回折扣价小于5supplies集合中的文档。

以下操作使用$expr operator 访问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的 value 修改输入文档。具体来说,它使用$gte比较qty并使用$multiply修改价格。

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

  • 文档id : 3qty50。 $cond返回price乘以0.75的结果,有效地应用25%折扣,产生的值。

  • $lt将返回的 value 与提供的 value 5进行比较。

  • 文档_id : 1cond返回6。由于$lt [6, 5]求值为 false,因此表达式不会_return 文档。

  • 文档_id : 3cond返回4。由于$lt [4, 5]求值为 true,表达式返回文档。

find()继续将$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修改输入文档作为查询过滤的一部分,但不会将修改保留到磁盘。结果表示原始 state 中的匹配文档。查找操作没有_return binderlegal pad文档,因为它们的修改价格大于5。特别:

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

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