@@ -141,13 +141,15 @@ Behavior
141141--------
142142
143143Document Pre- and Post-Images
144- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
144+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
145+
145146.. include:: /includes/change-stream-pre-and-post-images-change-events.rst
146147
147148.. include:: /includes/change-stream-pre-and-post-images-additional-information.rst
148149
149150Path Disambiguation
150- ^^^^^^^^^^^^^^^^^^^
151+ ~~~~~~~~~~~~~~~~~~~
152+
151153
152154.. versionadded:: 6.1
153155
@@ -223,6 +225,171 @@ numeric field:
223225* When the numeric string field has leading zeroes (i.e., ``0001``).
224226 This is not ambiguous since an integer cannot have leading zeroes.
225227
228+ Update Operations
229+ ~~~~~~~~~~~~~~~~~
230+
231+ .. include:: /includes/fact-modify-change-event
232+
233+ Array Updates
234+ ~~~~~~~~~~~~~
235+
236+ Updates to arrays produce ``update`` change events, but the
237+ ``updateDescription.updateFields`` can show different values.
238+
239+ For example, consider the following document and updates:
240+
241+ .. code-block:: javascript
242+
243+ db.students.insertOne( { student_id: 1, scores: [ ] } )
244+
245+ db.students.updateOne(
246+ { student_id: 1 },
247+ { $push: { scores: 0.85 } }
248+ )
249+
250+ db.students.updateOne(
251+ { student_id: 1 },
252+ { $push: { scores: 0.94 } }
253+ )
254+
255+ db.students.updateOne(
256+ { student_id: 1 },
257+ { $pull: { scores: 0.94 } }
258+ )
259+
260+ The first update operates on an empty array. Here, the
261+ :update:`$push` produces an ``update`` change event where the
262+ field is replaced by single-entry array with the given value:
263+
264+ .. code-block:: javascript
265+ :copyable: false
266+ :emphasize-lines: 8
267+
268+ {
269+ _id: { _data: '82642AD66B000000012B022C0100296E5A10045DC4B11BEA5F4319A8E7CAF46816ED71461E5F6964002B060004' },
270+ operationType: 'update',
271+ clusterTime: Timestamp({ t: 1680529003, i: 1 }),
272+ ns: { db: 'communication_chat', coll: 'students' },
273+ documentKey: { student_id: 1 },
274+ updateDescription: {
275+ updatedFields: { scores: [ 0.85 ] },
276+ removedFields: [],
277+ truncatedArrays: []
278+ }
279+ }
280+
281+ In the second update operation, the array now contains values.
282+ The :update:`$push` adds a new entry in the array. The
283+ ``update`` change event then shows it as a change on the new
284+ position in the array (that is, ``scores.1``):
285+
286+ .. code-block:: javascript
287+ :copyable: false
288+ :emphasize-lines: 8
289+
290+ {
291+ _id: { _data: '82642AD673000000012B022C0100296E5A10045DC4B11BEA5F4319A8E7CAF46816ED71461E5F6964002B060004' },
292+ operationType: 'update',
293+ clusterTime: Timestamp({ t: 1680529011, i: 1 }),
294+ ns: { db: 'communication_chat', coll: 'students' },
295+ documentKey: { student_id: 1 },
296+ updateDescription: {
297+ updatedFields: { 'scores.1': 0.94 },
298+ removedFields: [],
299+ truncatedArrays: []
300+ }
301+ }
302+
303+ If you run the update operation again to add a third score to
304+ the student's record, it would produce an ``update`` change
305+ event that modifies ``scores.2``.
306+
307+ Removal of array items with the :update:`$pull` operator
308+ produces a change event that shows the new array:
309+
310+ .. code-block:: javascript
311+ :copyable: false
312+ :emphasize-lines: 8
313+
314+ {
315+ _id: { _data: '82642AD673000000012B022C0100296E5A10045DC4B11BEA5F4319A8E7CAF46816ED71461E5F6964002B060004' },
316+ operationType: 'update',
317+ clusterTime: Timestamp({ t: 1680529011, i: 1 }),
318+ ns: { db: 'communication_chat', coll: 'students' },
319+ documentKey: { student_id: 1 },
320+ updateDescription: {
321+ updatedFields: { scores: [ 0.85 ] },
322+ removedFields: [],
323+ truncatedArrays: []
324+ }
325+ }
326+
327+ Array Truncation
328+ ~~~~~~~~~~~~~~~~
329+
330+ Update operations that reduce the number of elements in arrays
331+ through the :ref:`pipeline updates <updates-agg-pipeline>`, such
332+ as with the :pipeline:`$addFields` or :pipeline:`$set`
333+ aggregation stages, show the updated array and new size in the
334+ ``truncatedArrays`` field.
335+
336+ .. code-block:: javascript
337+
338+ db.students.insertOne( { student_id: 2, scores: [ 0.85, 0.94, 0.78 ] } )
339+
340+ db.students.updateOne(
341+ { student_id: 2 },
342+ [ { $addFields: { scores: [ 0.85, 0.94 ] } } ]
343+ )
344+
345+ db.students.updateOne(
346+ { student_id: 2 },
347+ [ { $addFields: { scores: [ 0.85, 0.94, 0.78 ] } } ]
348+ )
349+
350+ The change event from the first update, which used the
351+ :pipeline:`$addFields` stage to remove a value from the
352+ ``scores`` field shows the change in the ``truncatedArrays``
353+ field:
354+
355+ .. code-block:: javascript
356+ :copyable: false
357+ :emphasize-lines: 10
358+
359+ {
360+ _id: { _data: '82642AD673000000012B022C0100296E5A10045DC4B11BEA5F4319A8E7CAF46816ED71461E5F6964002B060004' },
361+ operationType: 'update',
362+ clusterTime: Timestamp({ t: 1680529011, i: 1 }),
363+ ns: { db: 'communication_chat', coll: 'students' },
364+ documentKey: { student_id: 2 },
365+ updateDescription: {
366+ updatedFields: {},
367+ removedFields: [],
368+ truncatedArrays: [ { fields: "scores", newSize: 2 } ]
369+ }
370+ }
371+
372+ The change event from the second update, which used the
373+ :pipeline:`$addFields` stage to add a value back to the
374+ ``scores`` field, shows the update in the ``updatedFields``
375+ field:
376+
377+ .. code-block:: javascript
378+ :copyable: false
379+ :emphasize-lines: 8
380+
381+ {
382+ _id: { _data: '82642AD673000000012B022C0100296E5A10045DC4B11BEA5F4319A8E7CAF46816ED71461E5F6964002B060004' },
383+ operationType: 'update',
384+ clusterTime: Timestamp({ t: 1680529011, i: 1 }),
385+ ns: { db: 'communication_chat', coll: 'students' },
386+ documentKey: { student_id: 2 },
387+ updateDescription: {
388+ updatedFields: { scores.2: 0.78 },
389+ removedFields: [],
390+ truncatedArrays: []
391+ }
392+ }
226393
227394Example
228395-------
0 commit comments