$first (aggregation accumulator)

On this page本页内容

Definition定义

$first

Changed in version 5.0.在版本5.0中更改

Returns the value that results from applying an expression to the first document in a group of documents. 返回将表达式应用于一组文档中的第一个文档所产生的值。Only meaningful when documents are in a defined order.仅当文档处于定义的顺序时才有意义。

$first is available in these stages:在以下阶段可用:

Note注意
Disambiguation消除歧义

This page describes the $first aggregation accumulator. 本页介绍$first聚合累加器。For the $first array operator, see $first (array operator).有关$first数组运算符,请参阅$first(数组运算符)。

Syntax语法

$first syntax:语法:

{ $first: <expression> }

For more information on expressions, see Expressions.有关表达式的详细信息,请参阅表达式

Behavior行为

To define the document order for $first with the:要定义$first的文档顺序,请使用:

Note注意

Although the $sort stage passes ordered documents as input to the $group and $setWindowFields stages, those stages are not guaranteed to maintain the sort order in their own output.尽管$sort阶段将有序文档作为输入传递给$group$setWindowFields阶段,但这些阶段不能保证在自己的输出中维护排序顺序。

When used with $setWindowFields, $first returns null for empty windows. $setWindowFields一起使用时,对于空窗口$first返回nullAn example empty window is a { documents: [ -1, -1 ] } documents window on the first document of a partition.空窗口的示例是分区第一个文档上的{ documents: [ -1, -1 ] }文档窗口。

Missing Values缺少值

The documents in a group may be missing fields or may have fields with missing values.组中的文档可能缺少字段,也可能包含缺少值的字段。

  • If there are no documents from the prior pipeline stage, the $group stage returns nothing.如果没有来自上一管道阶段的文档,$group阶段将不返回任何内容。
  • If the field that the $first accumulator is processing is missing, $first returns null.如果缺少$first累加器正在处理的字段,$first将返回null

See the missing data example.请参阅缺失数据示例。

Examples示例

Use in $group Stage$group阶段中使用

Create the sales collection:创建sales集合:

db.sales.insertMany( [
   { "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:00:00Z") },
   { "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-02-03T09:00:00Z") },
   { "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-03T09:05:00Z") },
   { "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-02-15T08:00:00Z") },
   { "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T09:05:00Z") },
   { "_id" : 6, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-15T12:05:10Z") },
   { "_id" : 7, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T14:12:12Z") }
] )

Grouping the documents by the item field, the following operation uses the $first accumulator to compute the first sales date for each item:以下操作按item字段对文档进行分组,使用$first累加器计算每个项目的第一个销售日期:

db.sales.aggregate(
   [
     { $sort: { item: 1, date: 1 } },
     {
       $group:
         {
           _id: "$item",
           firstSale: { $first: "$date" }
         }
     }
   ]
)

The operation returns the following results:该操作返回以下结果:

[
   { _id: 'jkl', firstSale: ISODate("2014-02-03T09:00:00.000Z") },
   { _id: 'xyz', firstSale: ISODate("2014-02-03T09:05:00.000Z") },
   { _id: 'abc', firstSale: ISODate("2014-01-01T08:00:00.000Z") }
]

Missing Data缺少数据

Some documents in the badData collection are missing fields, other documents are missing values.badData集合中的某些文档缺少字段,其他文档缺少值。

Create the badData collection:创建badData集合:

db.badData.insertMany( [
   { "_id": 1, "price": 6, "quantity": 6 },
   { "_id": 2, "item": "album", "price": 5 , "quantity": 5  },
   { "_id": 7, "item": "tape", "price": 6, "quantity": 6 },
   { "_id": 8, "price": 5, "quantity": 5  },
   { "_id": 9, "item": "album", "price": 3, "quantity": '' },
   { "_id": 10, "item": "tape", "price": 3, "quantity":  4 },
   { "_id": 12, "item": "cd", "price": 7  }
] )

Query the badData collection, grouping the output on the item field:查询badData集合,将item字段上的输出分组:

db.badData.aggregate( [
   { $sort: { item: 1, price: 1 } },
   { $group:
      {
         _id: "$item",
         inStock: { $first: "$quantity" }
      }
   }
] )

The $sort stage orders the documents and passes them to the $group stage.$sort阶段对文档进行排序并将其传递给$group阶段。

[
  { _id: null, inStock: 5 },
  { _id: 'album', inStock: '' },
  { _id: 'cd', inStock: null },
  { _id: 'tape', inStock: 4 }
]

$first selects the first document from each output group:从每个输出组中选择第一个文档:

  • The _id: null group is included.包含_id:null组。
  • When the accumulator field, $quantity in this example, is missing, $first returns null.当缺少累加器字段(本例中为$quantity)时,$first返回null

Use in $setWindowFields Stage$setWindowFields阶段中使用

New in version 5.0.在版本5.0中新增

Create a cakeSales collection that contains cake sales in the states of California (CA) and Washington (WA):创建包含加利福尼亚州(CA)和华盛顿州(WA)蛋糕销售的cakeSales系列:

db.cakeSales.insertMany( [
   { _id: 0, type: "chocolate", orderDate: new Date("2020-05-18T14:10:30Z"),
     state: "CA", price: 13, quantity: 120 },
   { _id: 1, type: "chocolate", orderDate: new Date("2021-03-20T11:30:05Z"),
     state: "WA", price: 14, quantity: 140 },
   { _id: 2, type: "vanilla", orderDate: new Date("2021-01-11T06:31:15Z"),
     state: "CA", price: 12, quantity: 145 },
   { _id: 3, type: "vanilla", orderDate: new Date("2020-02-08T13:13:23Z"),
     state: "WA", price: 13, quantity: 104 },
   { _id: 4, type: "strawberry", orderDate: new Date("2019-05-18T16:09:01Z"),
     state: "CA", price: 41, quantity: 162 },
   { _id: 5, type: "strawberry", orderDate: new Date("2019-01-08T06:12:03Z"),
     state: "WA", price: 43, quantity: 134 }
] )

This example uses $first in the $setWindowFields stage to output the first cake sales order type for each state:本例使用$setWindowFields阶段中的$first为每个state输出第一个蛋糕销售订单type

db.cakeSales.aggregate( [
   {
      $setWindowFields: {
         partitionBy: "$state",
         sortBy: { orderDate: 1 },
         output: {
            firstOrderTypeForState: {
               $first: "$type",
               window: {
                  documents: [ "unbounded", "current" ]
               }
            }
         }
      }
   }
] )

In the example:在该示例中:

  • partitionBy: "$state" partitions the documents in the collection by state. state对集合中的文档进行分区There are partitions for CA and WA.有用于CAWA的分区。
  • sortBy: { orderDate: 1 } sorts the documents in each partition by orderDate in ascending order (1), so the earliest orderDate is first.orderDate按升序(1)对每个分区中的文档进行排序,因此最早的orderDate是第一个。
  • output sets the firstOrderTypeForState field to the first order type from the documents window.文档窗口中的firstOrderTypeForState字段设置为第一个订单type

    The window contains documents between an unbounded lower limit and the current document in the output. 窗口包含输出中处于unbounded下限和current文档之间的文档。This means $first returns the first order type for the documents between the beginning of the partition and the current document.这意味着$first返回分区开头和当前文档之间的文档的第一顺序type

In this output, the first order type value for CA and WA is shown in the firstOrderTypeForState field:在此输出中,CA和WA的第一个订单type值显示在firstOrderTypeForState字段中:

{ "_id" : 4, "type" : "strawberry", "orderDate" : ISODate("2019-05-18T16:09:01Z"),
  "state" : "CA", "price" : 41, "quantity" : 162, "firstOrderTypeForState" : "strawberry" }
{ "_id" : 0, "type" : "chocolate", "orderDate" : ISODate("2020-05-18T14:10:30Z"),
  "state" : "CA", "price" : 13, "quantity" : 120, "firstOrderTypeForState" : "strawberry" }
{ "_id" : 2, "type" : "vanilla", "orderDate" : ISODate("2021-01-11T06:31:15Z"),
  "state" : "CA", "price" : 12, "quantity" : 145, "firstOrderTypeForState" : "strawberry" }
{ "_id" : 5, "type" : "strawberry", "orderDate" : ISODate("2019-01-08T06:12:03Z"),
  "state" : "WA", "price" : 43, "quantity" : 134, "firstOrderTypeForState" : "strawberry" }
{ "_id" : 3, "type" : "vanilla", "orderDate" : ISODate("2020-02-08T13:13:23Z"),
  "state" : "WA", "price" : 13, "quantity" : 104, "firstOrderTypeForState" : "strawberry" }
{ "_id" : 1, "type" : "chocolate", "orderDate" : ISODate("2021-03-20T11:30:05Z"),
  "state" : "WA", "price" : 14, "quantity" : 140, "firstOrderTypeForState" : "strawberry" }
←  $filter (aggregation)$firstN (aggregation accumulator) →