@@ -47,6 +47,19 @@ Behavior
47
47
48
48
.. include:: /includes/note-group-and-window-behavior.rst
49
49
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
+
50
63
Examples
51
64
--------
52
65
@@ -55,17 +68,19 @@ Examples
55
68
Use in ``$group`` Stage
56
69
~~~~~~~~~~~~~~~~~~~~~~~
57
70
58
- Consider a ``sales`` collection with the following documents :
71
+ Create the ``sales`` collection:
59
72
60
73
.. code-block:: javascript
61
74
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
+ ] )
69
84
70
85
Grouping the documents by the ``item`` field, the following operation
71
86
uses the :group:`$first` accumulator to compute the first sales date for
@@ -80,7 +95,7 @@ each item:
80
95
$group:
81
96
{
82
97
_id: "$item",
83
- firstSalesDate : { $first: "$date" }
98
+ firstSale : { $first: "$date" }
84
99
}
85
100
}
86
101
]
@@ -90,9 +105,66 @@ The operation returns the following results:
90
105
91
106
.. code-block:: javascript
92
107
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``.
96
168
97
169
.. _first-accumulator-window-example:
98
170
0 commit comments