Skip to content

Commit c1c2e68

Browse files
mungitoperritojeff-allen-mongo
authored andcommitted
DOCS-13415 clarify wording for unwind
1 parent d503c89 commit c1c2e68

File tree

1 file changed

+85
-49
lines changed

1 file changed

+85
-49
lines changed

source/reference/operator/aggregation/unwind.txt

Lines changed: 85 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@ field name with a dollar sign ``$`` and enclose in quotes.
4242
Document Operand with Options
4343
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4444

45-
.. versionadded:: 3.2
46-
4745
You can pass a document to :pipeline:`$unwind` to specify various
4846
behavior options.
4947

@@ -170,75 +168,80 @@ Each document is identical to the input document except for the value
170168
of 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+
272308
Group by Unwound Values
273309
~~~~~~~~~~~~~~~~~~~~~~~
274310

0 commit comments

Comments
 (0)