@@ -42,8 +42,6 @@ field name with a dollar sign ``$`` and enclose in quotes.
42
42
Document Operand with Options
43
43
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
44
44
45
- .. versionadded:: 3.2
46
-
47
45
You can pass a document to :pipeline:`$unwind` to specify various
48
46
behavior options.
49
47
@@ -170,75 +168,80 @@ Each document is identical to the input document except for the value
170
168
of the ``sizes`` field which now holds a value from the original
171
169
``sizes`` array.
172
170
173
- ``includeArrayIndex`` and ``preserveNullAndEmptyArrays``
174
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
175
-
176
- .. versionadded:: 3.2
171
+ Missing or Non-array Values
172
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
177
173
178
- In :binary:`~bin.mongosh`, create a sample collection named
179
- ``inventory2`` with the following documents:
174
+ Consider the ``clothing`` collection:
180
175
181
176
.. code-block:: javascript
182
177
183
- db.inventory2 .insertMany([
184
- { "_id" : 1, "item" : "ABC", price: NumberDecimal("80") , "sizes": [ "S", "M", "L"] },
185
- { "_id" : 2, "item" : "EFG", price: NumberDecimal("120") , "sizes" : [ ] },
186
- { "_id" : 3, "item" : "IJK", price: NumberDecimal("160") , "sizes": "M" },
187
- { "_id" : 4, "item" : "LMN" , price: NumberDecimal("10") },
188
- { "_id" : 5, "item" : "XYZ", price: NumberDecimal("5.75") , "sizes" : null }
178
+ db.clothing .insertMany([
179
+ { "_id" : 1, "item" : "Shirt" , "sizes": [ "S", "M", "L"] },
180
+ { "_id" : 2, "item" : "Shorts" , "sizes" : [ ] },
181
+ { "_id" : 3, "item" : "Hat" , "sizes": "M" },
182
+ { "_id" : 4, "item" : "Gloves" },
183
+ { "_id" : 5, "item" : "Scarf" , "sizes" : null }
189
184
])
190
185
191
- The following :pipeline:`$unwind` operations are equivalent and return
192
- a document for each element in the ``sizes`` field. If the ``sizes``
193
- field does not resolve to an array but is not missing, null, or an
194
- empty array, :pipeline:`$unwind` treats the non-array operand as a
195
- single element array.
186
+ :pipeline:`$unwind` treats the ``sizes`` field as a single element
187
+ array if:
188
+
189
+ - the field is present,
190
+ - the value is not null, and
191
+ - the value is not an empty array.
192
+
193
+ Expand the ``sizes`` arrays with :pipeline:`$unwind`:
196
194
197
195
.. code-block:: javascript
198
196
199
- db.inventory2.aggregate( [ { $unwind: "$sizes" } ] )
200
- db.inventory2.aggregate( [ { $unwind: { path: "$sizes" } } ] )
197
+ db.clothing.aggregate( [ { $unwind: { path: "$sizes" } } ] )
201
198
202
- The operation returns the following documents :
199
+ The :pipeline:`$unwind` operation returns:
203
200
204
201
.. code-block:: javascript
205
202
:copyable: false
206
203
207
- { " _id" : 1, " item" : "ABC", "price" : NumberDecimal("80"), " sizes" : "S" }
208
- { " _id" : 1, " item" : "ABC", "price" : NumberDecimal("80"), " sizes" : "M" }
209
- { " _id" : 1, " item" : "ABC", "price" : NumberDecimal("80"), " sizes" : "L" }
210
- { " _id" : 3, " item" : "IJK", "price" : NumberDecimal("160"), " sizes" : "M" }
204
+ { _id: 1, item: 'Shirt', sizes: 'S' },
205
+ { _id: 1, item: 'Shirt', sizes: 'M' },
206
+ { _id: 1, item: 'Shirt', sizes: 'L' },
207
+ { _id: 3, item: 'Hat', sizes: 'M' }
211
208
212
- ``includeArrayIndex``
213
- `````````````````````
209
+ - In document ``"_id": 1``, ``sizes`` is a populated array.
210
+ :pipeline:`$unwind` returns a document for each element in the
211
+ ``sizes`` field.
212
+ - In document ``"_id": 3``, ``sizes`` resolves to a single element
213
+ array.
214
+ - Documents ``"_id": 2, "_id": 4``, and ``"_id": 5`` do not return
215
+ anything because the ``sizes`` field cannot be reduced to a single
216
+ element array.
214
217
215
- The following :pipeline:`$unwind` operation uses the
216
- :ref:`includeArrayIndex <unwind-includeArrayIndex>` option to include
217
- the array index in the output.
218
+ .. note::
218
219
219
- .. code-block:: javascript
220
+ The ``{ path: <FIELD> }`` syntax is optional. The following
221
+ :pipeline:`$unwind` operations are equivalent.
220
222
221
- db.inventory2.aggregate( [
222
- {
223
- $unwind:
224
- {
225
- path: "$sizes",
226
- includeArrayIndex: "arrayIndex"
227
- }
228
- }])
223
+ .. code-block:: javascript
229
224
230
- The operation unwinds the ``sizes`` array and includes the array index
231
- of the array index in the new ``arrayIndex`` field. If the ``sizes``
232
- field does not resolve to an array but is not missing, null, or an
233
- empty array, the ``arrayIndex`` field is ``null``.
225
+ db.clothing.aggregate( [ { $unwind: "$sizes" } ] )
226
+ db.clothing.aggregate( [ { $unwind: { path: "$sizes" } } ] )
227
+
228
+ ``preserveNullAndEmptyArrays`` and ``includeArrayIndex``
229
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
230
+
231
+ The :ref:`ex-preservedNull` and :ref:`ex-includeArrayIndex` examples
232
+ use the following collection:
234
233
235
234
.. code-block:: javascript
236
- :copyable: false
237
235
238
- { "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "S", "arrayIndex" : NumberLong(0) }
239
- { "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "M", "arrayIndex" : NumberLong(1) }
240
- { "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "L", "arrayIndex" : NumberLong(2) }
241
- { "_id" : 3, "item" : "IJK", "price" : NumberDecimal("160"), "sizes" : "M", "arrayIndex" : null }
236
+ db.inventory2.insertMany([
237
+ { "_id" : 1, "item" : "ABC", price: NumberDecimal("80"), "sizes": [ "S", "M", "L"] },
238
+ { "_id" : 2, "item" : "EFG", price: NumberDecimal("120"), "sizes" : [ ] },
239
+ { "_id" : 3, "item" : "IJK", price: NumberDecimal("160"), "sizes": "M" },
240
+ { "_id" : 4, "item" : "LMN" , price: NumberDecimal("10") },
241
+ { "_id" : 5, "item" : "XYZ", price: NumberDecimal("5.75"), "sizes" : null }
242
+ ])
243
+
244
+ .. _ex-preservedNull:
242
245
243
246
``preserveNullAndEmptyArrays``
244
247
``````````````````````````````
@@ -269,6 +272,39 @@ null, missing, or an empty array:
269
272
{ "_id" : 4, "item" : "LMN", "price" : NumberDecimal("10") }
270
273
{ "_id" : 5, "item" : "XYZ", "price" : NumberDecimal("5.75"), "sizes" : null }
271
274
275
+ .. _ex-includeArrayIndex:
276
+
277
+ ``includeArrayIndex``
278
+ `````````````````````
279
+
280
+ The following :pipeline:`$unwind` operation uses the
281
+ :ref:`includeArrayIndex <unwind-includeArrayIndex>` option to include
282
+ the array index in the output.
283
+
284
+ .. code-block:: javascript
285
+
286
+ db.inventory2.aggregate( [
287
+ {
288
+ $unwind:
289
+ {
290
+ path: "$sizes",
291
+ includeArrayIndex: "arrayIndex"
292
+ }
293
+ }])
294
+
295
+ The operation unwinds the ``sizes`` array and includes the array index
296
+ in the new ``arrayIndex`` field. If the ``sizes`` field does not
297
+ resolve to a populated array but is not missing, null, or an empty
298
+ array, the ``arrayIndex`` field is ``null``.
299
+
300
+ .. code-block:: javascript
301
+ :copyable: false
302
+
303
+ { "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "S", "arrayIndex" : NumberLong(0) }
304
+ { "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "M", "arrayIndex" : NumberLong(1) }
305
+ { "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "L", "arrayIndex" : NumberLong(2) }
306
+ { "_id" : 3, "item" : "IJK", "price" : NumberDecimal("160"), "sizes" : "M", "arrayIndex" : null }
307
+
272
308
Group by Unwound Values
273
309
~~~~~~~~~~~~~~~~~~~~~~~
274
310
0 commit comments