Skip to content

Commit 93029e3

Browse files
kennethdyerKenneth P. J. Dyer
andauthored
DOCS-14267 Ambiguous Positional Operator (#254) (#498)
* DOCS-14267 Ambiguous Positional Operator * DOCS-14267 Ambiguous Positional Operator * DOCS-14267 Fixes from internal review * Merge * DOCS-14267 updates * DOCS-14267 adds 0 link to Behavior section * DOCS-14267 fixes to text * Fixes spacing * DOCS-14267 Reworks example description * DOCS-14267 Reworks text and code * DOCS-14267 Fixes from internal review * DOCS-14267 Reworks text for explanation * Text refactor * DOCS-14267 text refactor * DOCS-14267 Text refactor * DOCS-14267 text refactor and typos * DOCS-14267 Rework paragraphing, modified gerund to infinitive * DOCS-14267 Text refactor * DOCS-14267 typo * DOCS-14267 applies fixes from internal feedback * DOCS-14267 Fixes spacing in find() call * DOCS-14267 spacing adjustment, per feedback * DOCS-14267 Spacing fix * DOCS-14267 Term consistency * DOCS-14267 updates nomenclature for $ operator * DOCS-14267 Text adjustment per internal feedback * DOCS-14267 vale check Co-authored-by: Kenneth P. J. Dyer <[email protected]> Co-authored-by: Kenneth P. J. Dyer <[email protected]>
1 parent bb85172 commit 93029e3

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

source/reference/operator/update/positional.txt

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,19 @@ However, if the negated portion of the query is inside of an
9696
:query:`$elemMatch` expression, then you *can* use the positional
9797
operator to update this field.
9898

99+
Multiple Array Matches
100+
~~~~~~~~~~~~~~~~~~~~~~~
101+
102+
The positional :update:`$` update operator behaves ambiguously when filtering
103+
on multiple array fields.
104+
105+
When the server executes an update method, it first runs a query to determine
106+
which documents you want to update. If the update filters documents on multiple
107+
array fields, the subsequent call to the positional :update:`$` update operator
108+
doesn't always update the required position in the array.
109+
110+
For more information, see the :ref:`example <multiple-array-match>`.
111+
99112
Examples
100113
--------
101114

@@ -250,6 +263,66 @@ criteria, namely the second embedded document in the array:
250263
]
251264
}
252265

266+
.. _multiple-array-match:
267+
268+
Update with Multiple Array Matches
269+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
270+
271+
The positional :update:`$` update operator behaves ambiguously when the
272+
query has multiple array fields to filter documents in the collection.
273+
274+
Consider a document in the ``students_deans_list`` collection, which holds
275+
arrays of student information:
276+
277+
.. code-block:: javascript
278+
279+
db.students_deans_list.insertMany( [
280+
{
281+
_id: 8,
282+
activity_ids: [ 1, 2 ],
283+
grades: [ 90, 95 ],
284+
deans_list: [ 2021, 2020 ]
285+
}
286+
] )
287+
288+
In the following example, the user attempts to modify the ``deans_list`` field,
289+
filtering documents using the ``activity_ids``, ``deans_list``, and ``grades``
290+
fields, and updating the 2021 value in the ``deans_list`` field to 2022:
291+
292+
.. code-block:: javascript
293+
294+
db.students_deans_list.updateOne(
295+
{ activity_ids: 1, grades: 95, deans_list: 2021 },
296+
{ $set: { "deans_list.$": 2022 } }
297+
)
298+
299+
When the server executes the ``updateOne`` method above, it filters
300+
the available documents using values in the supplied array fields.
301+
Although the ``deans_list`` field is used in the filter, it is not the field
302+
used by the positional :update:`$` update operator to determine which position
303+
in the array to update:
304+
305+
.. code-block:: javascript
306+
307+
db.students_deans_list.find( { _id: 8 } )
308+
309+
Example output:
310+
311+
.. code-block:: javascript
312+
313+
{
314+
_id: 8,
315+
activity_ids: [ 1, 2 ],
316+
grades: [ 90, 95 ],
317+
deans_list: [ 2021, 2022 ]
318+
}
319+
320+
The ``updateOne`` method matched the ``deans_list`` field on 2021, but the
321+
positional :update:`$` update operator instead changed the 2020 value to 2022.
322+
323+
To avoid unexpected results when matching on multiple arrays, instead
324+
use the filtered positional operator :update:`$[<identifier>]`.
325+
253326
.. seealso::
254327

255328
- :method:`db.collection.update()`

0 commit comments

Comments
 (0)