@@ -42,8 +42,6 @@ field name with a dollar sign ``$`` and enclose in quotes.
4242Document Operand with Options
4343~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4444
45- .. versionadded:: 3.2
46-
4745You can pass a document to :pipeline:`$unwind` to specify various
4846behavior options.
4947
@@ -170,75 +168,80 @@ Each document is identical to the input document except for the value
170168of the ``sizes`` field which now holds a value from the original
171169``sizes`` array.
172170
173- ``includeArrayIndex`` and ``preserveNullAndEmptyArrays``
174- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
175-
176- .. versionadded:: 3.2
171+ Missing or Non-array Values
172+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
177173
178- In :binary:`~bin.mongosh`, create a sample collection named
179- ``inventory2`` with the following documents:
174+ Consider the ``clothing`` collection:
180175
181176.. code-block:: javascript
182177
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 }
189184 ])
190185
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`:
196194
197195.. code-block:: javascript
198196
199- db.inventory2.aggregate( [ { $unwind: "$sizes" } ] )
200- db.inventory2.aggregate( [ { $unwind: { path: "$sizes" } } ] )
197+ db.clothing.aggregate( [ { $unwind: { path: "$sizes" } } ] )
201198
202- The operation returns the following documents :
199+ The :pipeline:`$unwind` operation returns:
203200
204201.. code-block:: javascript
205202 :copyable: false
206203
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' }
211208
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.
214217
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::
218219
219- .. code-block:: javascript
220+ The ``{ path: <FIELD> }`` syntax is optional. The following
221+ :pipeline:`$unwind` operations are equivalent.
220222
221- db.inventory2.aggregate( [
222- {
223- $unwind:
224- {
225- path: "$sizes",
226- includeArrayIndex: "arrayIndex"
227- }
228- }])
223+ .. code-block:: javascript
229224
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:
234233
235234.. code-block:: javascript
236- :copyable: false
237235
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:
242245
243246``preserveNullAndEmptyArrays``
244247``````````````````````````````
@@ -269,6 +272,39 @@ null, missing, or an empty array:
269272 { "_id" : 4, "item" : "LMN", "price" : NumberDecimal("10") }
270273 { "_id" : 5, "item" : "XYZ", "price" : NumberDecimal("5.75"), "sizes" : null }
271274
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+
272308Group by Unwound Values
273309~~~~~~~~~~~~~~~~~~~~~~~
274310
0 commit comments