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