@@ -96,6 +96,19 @@ However, if the negated portion of the query is inside of an
96
96
:query:`$elemMatch` expression, then you *can* use the positional
97
97
operator to update this field.
98
98
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
+
99
112
Examples
100
113
--------
101
114
@@ -250,6 +263,66 @@ criteria, namely the second embedded document in the array:
250
263
]
251
264
}
252
265
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
+
253
326
.. seealso::
254
327
255
328
- :method:`db.collection.update()`
0 commit comments