@@ -47,6 +47,19 @@ Behavior
4747
4848.. include:: /includes/note-group-and-window-behavior.rst
4949
50+ Missing Values
51+ ~~~~~~~~~~~~~~
52+
53+ The documents in a group may be missing fields or may have fields with
54+ missing values.
55+
56+ - If there are no documents from the prior pipeline stage, the
57+ :pipeline:`$group` stage returns nothing.
58+ - If the field that the :group:`$first` accumulator is processing is
59+ missing, :group:`$first` returns ``null``.
60+
61+ See the :ref:`missing data <first-missing-values-example>` example.
62+
5063Examples
5164--------
5265
@@ -55,17 +68,19 @@ Examples
5568Use in ``$group`` Stage
5669~~~~~~~~~~~~~~~~~~~~~~~
5770
58- Consider a ``sales`` collection with the following documents :
71+ Create the ``sales`` collection:
5972
6073.. code-block:: javascript
6174
62- { "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:00:00Z") }
63- { "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-02-03T09:00:00Z") }
64- { "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-03T09:05:00Z") }
65- { "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-02-15T08:00:00Z") }
66- { "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T09:05:00Z") }
67- { "_id" : 6, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-15T12:05:10Z") }
68- { "_id" : 7, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T14:12:12Z") }
75+ db.sales.insertMany( [
76+ { "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:00:00Z") },
77+ { "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-02-03T09:00:00Z") },
78+ { "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-03T09:05:00Z") },
79+ { "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-02-15T08:00:00Z") },
80+ { "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T09:05:00Z") },
81+ { "_id" : 6, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-15T12:05:10Z") },
82+ { "_id" : 7, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T14:12:12Z") }
83+ ] )
6984
7085Grouping the documents by the ``item`` field, the following operation
7186uses the :group:`$first` accumulator to compute the first sales date for
@@ -80,7 +95,7 @@ each item:
8095 $group:
8196 {
8297 _id: "$item",
83- firstSalesDate : { $first: "$date" }
98+ firstSale : { $first: "$date" }
8499 }
85100 }
86101 ]
@@ -90,9 +105,66 @@ The operation returns the following results:
90105
91106.. code-block:: javascript
92107
93- { "_id" : "xyz", "firstSalesDate" : ISODate("2014-02-03T09:05:00Z") }
94- { "_id" : "jkl", "firstSalesDate" : ISODate("2014-02-03T09:00:00Z") }
95- { "_id" : "abc", "firstSalesDate" : ISODate("2014-01-01T08:00:00Z") }
108+ [
109+ { _id: 'jkl', firstSale: ISODate("2014-02-03T09:00:00.000Z") },
110+ { _id: 'xyz', firstSale: ISODate("2014-02-03T09:05:00.000Z") },
111+ { _id: 'abc', firstSale: ISODate("2014-01-01T08:00:00.000Z") }
112+ ]
113+
114+ .. _first-missing-values-example:
115+
116+ Missing Data
117+ ~~~~~~~~~~~~
118+
119+ Some documents in the ``badData`` collection are missing fields, other
120+ documents are missing values.
121+
122+ Create the ``badData`` collection:
123+
124+ .. code-block:: javascript
125+
126+ db.badData.insertMany( [
127+ { "_id": 1, "price": 6, "quantity": 6 },
128+ { "_id": 2, "item": "album", "price": 5 , "quantity": 5 },
129+ { "_id": 7, "item": "tape", "price": 6, "quantity": 6 },
130+ { "_id": 8, "price": 5, "quantity": 5 },
131+ { "_id": 9, "item": "album", "price": 3, "quantity": '' },
132+ { "_id": 10, "item": "tape", "price": 3, "quantity": 4 },
133+ { "_id": 12, "item": "cd", "price": 7 }
134+ ] )
135+
136+ Query the ``badData`` collection, grouping the output on the ``item``
137+ field:
138+
139+ .. code-block:: javascript
140+
141+ db.badData.aggregate( [
142+ { $sort: { item: 1, price: 1 } },
143+ { $group:
144+ {
145+ _id: "$item",
146+ inStock: { $first: "$quantity" }
147+ }
148+ }
149+ ] )
150+
151+ The :pipeline:`$sort` stage orders the documents and passes them to the
152+ :pipeline:`$group` stage.
153+
154+ .. code-block:: javascript
155+
156+ [
157+ { _id: null, inStock: 5 },
158+ { _id: 'album', inStock: '' },
159+ { _id: 'cd', inStock: null },
160+ { _id: 'tape', inStock: 4 }
161+ ]
162+
163+ :group:`$first` selects the first document from each output group:
164+
165+ - The ``_id: null`` group is included.
166+ - When the accumulator field, ``$quantity`` in this example, is
167+ missing, :group:`$first` returns ``null``.
96168
97169.. _first-accumulator-window-example:
98170
0 commit comments