Skip to content

Commit ad043a4

Browse files
DOCSP-34027 Change Streams (#223)
1 parent 7fdd685 commit ad043a4

File tree

3 files changed

+418
-0
lines changed

3 files changed

+418
-0
lines changed

source/fundamentals/crud/read-operations.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Read Operations
1212

1313
/fundamentals/crud/read-operations/retrieve
1414
/fundamentals/crud/read-operations/count
15+
/fundamentals/crud/read-operations/change-streams
1516

1617
- :ref:`csharp-retrieve`
1718
- :ref:`csharp-count-documents`
19+
- :ref:`csharp-change-streams`
Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
.. _csharp-change-streams:
2+
3+
====================
4+
Monitor Data Changes
5+
====================
6+
7+
.. contents:: On this page
8+
:local:
9+
:backlinks: none
10+
:depth: 2
11+
:class: singlecol
12+
13+
.. facet::
14+
:name: genre
15+
:values: reference
16+
17+
.. meta::
18+
:keywords: watch, code example
19+
20+
Overview
21+
--------
22+
23+
In this guide, you can learn how to use a **change stream** to monitor real-time
24+
changes to your data. A change stream is a {+mdb-server+} feature that
25+
allows your application to subscribe to data changes on a collection, database,
26+
or deployment.
27+
28+
Sample Data
29+
~~~~~~~~~~~
30+
31+
The examples in this guide use the ``sample_restaurants.restaurants`` collection
32+
from the :atlas:`Atlas sample datasets </sample-data>`. To learn how to create a
33+
free MongoDB Atlas cluster and load the sample datasets, see the :ref:`<csharp-quickstart>`.
34+
35+
The examples on this page use the following ``Restaurant``, ``Address``, and ``GradeEntry``
36+
classes as models:
37+
38+
.. literalinclude:: /includes/code-examples/Restaurant.cs
39+
:language: csharp
40+
:copyable:
41+
:dedent:
42+
43+
.. literalinclude:: /includes/code-examples/Address.cs
44+
:language: csharp
45+
:copyable:
46+
:dedent:
47+
48+
.. literalinclude:: /includes/code-examples/GradeEntry.cs
49+
:language: csharp
50+
:copyable:
51+
:dedent:
52+
53+
.. include:: /includes/convention-pack-note.rst
54+
55+
Open a Change Stream
56+
--------------------
57+
58+
To open a change stream, call the ``Watch()`` or ``WatchAsync()`` method. The instance on which you
59+
call the method determines the scope of events that the change
60+
stream listens for. You can call the ``Watch()`` or ``WatchAsync()`` method on the following
61+
classes:
62+
63+
- ``MongoClient``: To monitor all changes in the MongoDB deployment
64+
- ``Database``: To monitor changes in all collections in the database
65+
- ``Collection``: To monitor changes in the collection
66+
67+
The following example opens a change stream on the ``restaurants`` collection
68+
and outputs the changes as they occur. Select the
69+
:guilabel:`Asynchronous` or :guilabel:`Synchronous` tab to see the corresponding
70+
code.
71+
72+
.. tabs::
73+
74+
.. tab:: Asynchronous
75+
:tabid: change-stream-async
76+
77+
.. literalinclude:: /includes/code-examples/change-streams/change-streams.cs
78+
:start-after: start-open-change-stream-async
79+
:end-before: end-open-change-stream-async
80+
:language: csharp
81+
82+
.. tab:: Synchronous
83+
:tabid: change-stream-sync
84+
85+
.. literalinclude:: /includes/code-examples/change-streams/change-streams.cs
86+
:start-after: start-open-change-stream
87+
:end-before: end-open-change-stream
88+
:language: csharp
89+
90+
To begin watching for changes, run the application. Then, in a separate
91+
application or shell, modify the ``restaurants`` collection. Updating a document
92+
that has a ``"name"`` value of ``"Blarney Castle"`` results in the following
93+
change stream output:
94+
95+
.. code-block:: sh
96+
:copyable: false
97+
98+
{ "_id" : { "_data" : "..." }, "operationType" : "update", "clusterTime" : Timestamp(...),
99+
"wallTime" : ISODate("..."), "ns" : { "db" : "sample_restaurants", "coll" : "restaurants" },
100+
"documentKey" : { "_id" : ObjectId("...") }, "updateDescription" : { "updatedFields" : { "cuisine" : "Irish" },
101+
"removedFields" : [], "truncatedArrays" : [] } }
102+
103+
Modify the Change Stream Output
104+
-------------------------------
105+
106+
You can pass the ``pipeline`` parameter to the ``Watch()`` and ``WatchAsync()``
107+
methods to modify the change stream output. This parameter allows you to watch
108+
for only specified change events. Create the pipeline by using the
109+
``EmptyPipelineDefinition`` class and appending the relevant aggregation stage methods.
110+
111+
You can specify the following aggregation stages in the ``pipeline`` parameter:
112+
113+
- ``$addFields``
114+
- ``$match``
115+
- ``$project``
116+
- ``$replaceRoot``
117+
- ``$replaceWith``
118+
- ``$redact``
119+
- ``$set``
120+
- ``$unset``
121+
122+
To learn how to build an aggregation pipeline by using the
123+
``PipelineDefinitionBuilder`` class, see :ref:`csharp-builders-aggregation` in
124+
the Operations with Builders guide.
125+
126+
The following example uses the ``pipeline`` parameter to open a change stream
127+
that records only update operations. Select the :guilabel:`Asynchronous` or :guilabel:`Synchronous` tab to see the
128+
corresponding code.
129+
130+
.. tabs::
131+
132+
.. tab:: Asynchronous
133+
:tabid: change-stream-async
134+
135+
.. literalinclude:: /includes/code-examples/change-streams/change-streams.cs
136+
:start-after: start-change-stream-pipeline-async
137+
:end-before: end-change-stream-pipeline-async
138+
:language: csharp
139+
140+
.. tab:: Synchronous
141+
:tabid: change-stream-sync
142+
143+
.. literalinclude:: /includes/code-examples/change-streams/change-streams.cs
144+
:start-after: start-change-stream-pipeline
145+
:end-before: end-change-stream-pipeline
146+
:language: csharp
147+
148+
To learn more about modifying your change stream output, see the
149+
:manual:`Modify Change Stream Output
150+
</changeStreams/#modify-change-stream-output>` section in the {+mdb-server+}
151+
manual.
152+
153+
Modify ``Watch()`` Behavior
154+
---------------------------
155+
156+
The ``Watch()`` and ``WatchAsync()`` methods accept optional parameters, which represent
157+
options you can use to configure the operation. If you don't specify any
158+
options, the driver does not customize the operation.
159+
160+
The following table describes the options you can set to customize the behavior
161+
of ``Watch()`` and ``WatchAsync()``:
162+
163+
.. list-table::
164+
:widths: 30 70
165+
:header-rows: 1
166+
167+
* - Option
168+
- Description
169+
170+
* - ``FullDocument``
171+
- | Specifies whether to show the full document after the change, rather
172+
than showing only the changes made to the document. To learn more about
173+
this option, see :ref:`csharp-change-stream-pre-post-image`.
174+
175+
* - ``FullDocumentBeforeChange``
176+
- | Specifies whether to show the full document as it was before the change, rather
177+
than showing only the changes made to the document. To learn more about
178+
this option, see :ref:`csharp-change-stream-pre-post-image`.
179+
180+
* - ``ResumeAfter``
181+
- | Directs ``Watch()`` or ``WatchAsync()`` to resume returning changes after the
182+
operation specified in the resume token.
183+
| Each change stream event document includes a resume token as the ``_id``
184+
field. Pass the entire ``_id`` field of the change event document that
185+
represents the operation you want to resume after.
186+
| ``ResumeAfter`` is mutually exclusive with ``StartAfter`` and ``StartAtOperationTime``.
187+
188+
* - ``StartAfter``
189+
- | Directs ``Watch()`` or ``WatchAsync()`` to start a new change stream after the
190+
operation specified in the resume token. Allows notifications to
191+
resume after an invalidate event.
192+
| Each change stream event document includes a resume token as the ``_id``
193+
field. Pass the entire ``_id`` field of the change event document that
194+
represents the operation you want to resume after.
195+
| ``StartAfter`` is mutually exclusive with ``ResumeAfter`` and ``StartAtOperationTime``.
196+
197+
* - ``StartAtOperationTime``
198+
- | Directs ``Watch()`` or ``WatchAsync()`` to return only events that occur after the
199+
specified timestamp.
200+
| ``StartAtOperationTime`` is mutually exclusive with ``ResumeAfter`` and ``StartAfter``.
201+
202+
* - ``MaxAwaitTime``
203+
- | Specifies the maximum amount of time, in milliseconds, the server waits for new
204+
data changes to report to the change stream cursor before returning an
205+
empty batch. Defaults to 1000 milliseconds.
206+
207+
* - ``ShowExpandedEvents``
208+
- | Starting in {+mdb-server+} v6.0, change streams support change notifications
209+
for Data Definition Language (DDL) events, such as the ``createIndexes`` and ``dropIndexes`` events. To
210+
include expanded events in a change stream, create the change stream
211+
cursor and set this parameter to ``True``.
212+
213+
* - ``BatchSize``
214+
- | Specifies the maximum number of change events to return in each batch of the
215+
response from the MongoDB cluster.
216+
217+
* - ``Collation``
218+
- | Specifies the collation to use for the change stream cursor.
219+
220+
* - ``Comment``
221+
- | Attaches a comment to the operation.
222+
223+
.. _csharp-change-stream-pre-post-image:
224+
225+
Include Pre-Images and Post-Images
226+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
227+
228+
.. important::
229+
230+
You can enable pre-images and post-images on collections only if your
231+
deployment uses MongoDB v6.0 or later.
232+
233+
By default, when you perform an operation on a collection, the
234+
corresponding change event includes only the delta of the fields
235+
modified by that operation. To see the full document before or after a
236+
change, create a ``ChangeStreamOptions`` object and specify the
237+
``FullDocumentBeforeChange`` or the ``FullDocument`` options. Then, pass the
238+
``ChangeStreamOptions`` object to the ``Watch()`` or ``WatchAsync()`` method.
239+
240+
The **pre-image** is the full version of a document *before* a change. To include the
241+
pre-image in the change stream event, set the ``FullDocumentBeforeChange``
242+
option to one of the following values:
243+
244+
- ``ChangeStreamFullDocumentBeforeChangeOption.WhenAvailable``: The change event
245+
includes a pre-image of the modified document for change events only if the
246+
pre-image is available.
247+
- ``ChangeStreamFullDocumentBeforeChangeOption.Required``:
248+
The change event includes a pre-image of the modified document for change
249+
events. If the pre-image is not available, the driver raises an error.
250+
251+
The **post-image** is the full version of a document *after* a change. To include the
252+
post-image in the change stream event, set the ``FullDocument`` option to
253+
one of the following values:
254+
255+
- ``ChangeStreamFullDocumentOption.UpdateLookup``: The change event includes a
256+
copy of the entire changed document from some time after the change.
257+
- ``ChangeStreamFullDocumentOption.WhenAvailable``: The change event includes a
258+
post-image of the modified document for change events only if the post-image
259+
is available.
260+
- ``ChangeStreamFullDocumentOption.Required``: The change event includes a
261+
post-image of the modified document for change events. If the post-image is
262+
not available, the driver raises an error.
263+
264+
The following example opens a change stream on a collection and includes the post-image
265+
of updated documents by specifying the ``FullDocument`` option. Select the
266+
:guilabel:`Asynchronous` or :guilabel:`Synchronous` tab to see the corresponding
267+
code.
268+
269+
.. tabs::
270+
271+
.. tab:: Asynchronous
272+
:tabid: change-stream-async
273+
274+
.. literalinclude:: /includes/code-examples/change-streams/change-streams.cs
275+
:start-after: start-change-stream-post-image-async
276+
:end-before: end-change-stream-post-image-async
277+
:language: csharp
278+
279+
.. tab:: Synchronous
280+
:tabid: change-stream-sync
281+
282+
.. literalinclude:: /includes/code-examples/change-streams/change-streams.cs
283+
:start-after: start-change-stream-post-image
284+
:end-before: end-change-stream-post-image
285+
:language: csharp
286+
287+
Running the preceding code example and updating a document that has a ``"name"``
288+
value of ``"Blarney Castle"`` results in the following change stream output:
289+
290+
.. code-block:: sh
291+
:copyable: false
292+
293+
{ "_id" : ObjectId("..."), "name" : "Blarney Castle", "restaurant_id" : "40366356",
294+
"cuisine" : "Traditional Irish", "address" : { "building" : "202-24", "coord" : [-73.925044200000002, 40.5595462],
295+
"street" : "Rockaway Point Boulevard", "zipcode" : "11697" }, "borough" : "Queens", "grades" : [...] }
296+
297+
To learn more about pre-images and post-images, see
298+
:manual:`Change Streams with Document Pre- and Post-Images </changeStreams#change-streams-with-document-pre--and-post-images>`
299+
in the {+mdb-server+} manual.
300+
301+
Additional Information
302+
----------------------
303+
304+
To learn more about change streams, see :manual:`Change Streams
305+
</changeStreams>` in the {+mdb-server+} manual.
306+
307+
API Documentation
308+
~~~~~~~~~~~~~~~~~
309+
310+
To learn more about any of the methods or types discussed in this
311+
guide, see the following API documentation:
312+
313+
- `Watch() <{+new-api-root+}/MongoDB.Driver/MongoDB.Driver.IMongoClient.Watch.html>`__
314+
- `WatchAsync() <{+new-api-root+}/MongoDB.Driver/MongoDB.Driver.IMongoClient.WatchAsync.html>`__
315+
- `ChangeStreamOptions <{+new-api-root+}/MongoDB.Driver/MongoDB.Driver.ChangeStreamOptions.html>`__
316+
- `UpdateOne() <{+new-api-root+}/MongoDB.Driver/MongoDB.Driver.IMongoCollectionExtensions.UpdateOne.html>`__

0 commit comments

Comments
 (0)