@@ -48,20 +48,42 @@ value depends on the order of the documents coming into pipeline. To
48
48
guarantee a defined order, the :pipeline:`$group` pipeline stage should
49
49
follow a :pipeline:`$sort` stage.
50
50
51
- Example
52
- -------
51
+ .. include:: /includes/note-group-and-window-behavior.rst
53
52
54
- Consider a ``sales`` collection with the following documents:
53
+ Missing Values
54
+ ~~~~~~~~~~~~~~
55
+
56
+ The documents in a group may be missing fields or may have fields with
57
+ missing values.
58
+
59
+ - If there are no documents from the prior pipeline stage, the
60
+ :pipeline:`$group` stage returns nothing.
61
+ - If the field that the :group:`$first` accumulator is processing is
62
+ missing, :group:`$first` returns ``null``.
63
+
64
+ See the :ref:`missing data <first-missing-values-example>` example.
65
+
66
+ Examples
67
+ --------
68
+
69
+ .. _first-accumulator-group-example:
70
+
71
+ Use in ``$group`` Stage
72
+ ~~~~~~~~~~~~~~~~~~~~~~~
73
+
74
+ Create the ``sales`` collection:
55
75
56
76
.. code-block:: javascript
57
77
58
- { "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:00:00Z") }
59
- { "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-02-03T09:00:00Z") }
60
- { "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-03T09:05:00Z") }
61
- { "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-02-15T08:00:00Z") }
62
- { "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T09:05:00Z") }
63
- { "_id" : 6, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-15T12:05:10Z") }
64
- { "_id" : 7, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T14:12:12Z") }
78
+ db.sales.insertMany( [
79
+ { "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:00:00Z") },
80
+ { "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-02-03T09:00:00Z") },
81
+ { "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-03T09:05:00Z") },
82
+ { "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-02-15T08:00:00Z") },
83
+ { "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T09:05:00Z") },
84
+ { "_id" : 6, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-15T12:05:10Z") },
85
+ { "_id" : 7, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T14:12:12Z") }
86
+ ] )
65
87
66
88
Grouping the documents by the ``item`` field, the following operation
67
89
uses the :group:`$first` accumulator to compute the first sales date for
@@ -76,7 +98,7 @@ each item:
76
98
$group:
77
99
{
78
100
_id: "$item",
79
- firstSalesDate : { $first: "$date" }
101
+ firstSale : { $first: "$date" }
80
102
}
81
103
}
82
104
]
@@ -86,6 +108,64 @@ The operation returns the following results:
86
108
87
109
.. code-block:: javascript
88
110
89
- { "_id" : "xyz", "firstSalesDate" : ISODate("2014-02-03T09:05:00Z") }
90
- { "_id" : "jkl", "firstSalesDate" : ISODate("2014-02-03T09:00:00Z") }
91
- { "_id" : "abc", "firstSalesDate" : ISODate("2014-01-01T08:00:00Z") }
111
+ [
112
+ { _id: 'jkl', firstSale: ISODate("2014-02-03T09:00:00.000Z") },
113
+ { _id: 'xyz', firstSale: ISODate("2014-02-03T09:05:00.000Z") },
114
+ { _id: 'abc', firstSale: ISODate("2014-01-01T08:00:00.000Z") }
115
+ ]
116
+
117
+ .. _first-missing-values-example:
118
+
119
+ Missing Data
120
+ ~~~~~~~~~~~~
121
+
122
+ Some documents in the ``badData`` collection are missing fields, other
123
+ documents are missing values.
124
+
125
+ Create the ``badData`` collection:
126
+
127
+ .. code-block:: javascript
128
+
129
+ db.badData.insertMany( [
130
+ { "_id": 1, "price": 6, "quantity": 6 },
131
+ { "_id": 2, "item": "album", "price": 5 , "quantity": 5 },
132
+ { "_id": 7, "item": "tape", "price": 6, "quantity": 6 },
133
+ { "_id": 8, "price": 5, "quantity": 5 },
134
+ { "_id": 9, "item": "album", "price": 3, "quantity": '' },
135
+ { "_id": 10, "item": "tape", "price": 3, "quantity": 4 },
136
+ { "_id": 12, "item": "cd", "price": 7 }
137
+ ] )
138
+
139
+ Query the ``badData`` collection, grouping the output on the ``item``
140
+ field:
141
+
142
+ .. code-block:: javascript
143
+
144
+ db.badData.aggregate( [
145
+ { $sort: { item: 1, price: 1 } },
146
+ { $group:
147
+ {
148
+ _id: "$item",
149
+ inStock: { $first: "$quantity" }
150
+ }
151
+ }
152
+ ] )
153
+
154
+ The :pipeline:`$sort` stage orders the documents and passes them to the
155
+ :pipeline:`$group` stage.
156
+
157
+ .. code-block:: javascript
158
+
159
+ [
160
+ { _id: null, inStock: 5 },
161
+ { _id: 'album', inStock: '' },
162
+ { _id: 'cd', inStock: null },
163
+ { _id: 'tape', inStock: 4 }
164
+ ]
165
+
166
+ :group:`$first` selects the first document from each output group:
167
+
168
+ - The ``_id: null`` group is included.
169
+ - When the accumulator field, ``$quantity`` in this example, is
170
+ missing, :group:`$first` returns ``null``.
171
+
0 commit comments