MongoDB Developer
Swift
MongoDB Developer Centerchevron-right
Developer Topicschevron-right
Languageschevron-right
Swiftchevron-right

Working with Change Streams from Your Swift Application

Andrew MorganPublished Jan 25, 2023 • Updated Jan 25, 2023
MongoDBChange StreamsSwift
FULL APPLICATION
Copy Link
facebook icontwitter iconlinkedin icon
random alt
Rate this quickstart
star-empty
star-empty
star-empty
star-empty
star-empty
My day job is to work with our biggest customers to help them get the best out of MongoDB when creating new applications or migrating existing ones. Their use cases often need side effects to be run whenever data changes — one of the most common requirements is to maintain an audit trail.
When customers are using MongoDB Atlas, it's a no-brainer to recommend Atlas Triggers. With triggers, you provide the code, and Atlas makes sure that it runs whenever the data you care about changes. There's no need to stand up an app server, and triggers are very efficient as they run alongside your data.
Unfortunately, there are still some workloads that customers aren't ready to move to the public cloud. For these applications, I recommend change streams. Change streams are the underlying mechanism used by Triggers and many other MongoDB technologies — Kafka Connector, Charts, Spark Connector, Atlas Search, anything that needs to react to data changes.
Using change streams is surprisingly easy. Ask the MongoDB Driver to open a change stream and it returns a database cursor. Listen to that cursor, and your application receives an event for every change in your collection.
This post shows you how to use change streams from a Swift application. The principles are exactly the same for other languages. You can find a lot more on change streams at Developer Center.

Running the example code

I recently started using the MongoDB Swift Driver for the first time. I decided to build a super-simple Mac desktop app that lets you browse your collections (which MongoDB Compass does a much better job of) and displays change stream events in real time (which Compass doesn't currently do).
You can download the code from the Swift-Change-Streams repo. Just build and run from Xcode.
Provide your connection-string and then browse your collections. Select the "Enable change streams" option to display change events in real time.
A simple desktop browser, connecting to a MongoDB cluster, browsing the collections, and enabling Change Streams. We then see change-stream events shown in the tool. Changes showup as a yellow JSON document which shows the changes as well as the new doc. Inserts show as green, and deletes as red.
The code
You can find this code in CollectionView.swift.
We need a variable to store the change stream (a database cursor)
as well as one to store the latest change event received from the change stream (this will be used to update the UI):
The registerChangeStream function is called whenever the user checks or unchecks the change stream option:
The function specifies what data it wants to see by creating a ChangeStreamOptions structure — you can see the available options in the Swift driver docs. In this app, I specify that I want to receive the complete new document (in addition to the deltas) when a document is updated. Note that the full document is always included for insert and replace operations.
The code then calls watch on the current collection. Note that you can also provide an aggregation pipeline as a parameter named pipeline when calling watch. That pipeline can filter and reshape the events your application receives.
Once the asynchronous watch function completes, the forEach loop processes each change event as it's received.
When the loop updates our latestChangeEvent variable, the change is automatically propagated to the ChangeEventView:
You can see all of the code to display the change event in ChangeEventView.swift. I'll show some highlights here.
The view receives the change event from the enclosing view (CollectionView):
The code looks at the operationType value in the event to determine what color to use for the window:
documentKey contains the _id value for the document that was changed in the MongoDB collection:
If the database operation was an update, then the delta is stored in updateDescription:
The complete document after the change was applied in MongoDB is stored in fullDocument:
If the processing of the change events is a critical process, then you need to handle events such as your process crashing.
The _id.resumeToken in the ChangeStreamEvent is a token that can be used when starting the process to continue from where you left off. Simply provide this token to the resumeAfter or startAfter options when opening the change stream. Note that this assumes that the events you've missed haven't rotated out of the Oplog.
Conclusion
Use Change Streams (or Atlas triggers, if you're able) to simplify your code base by decoupling the handling of side-effects from each place in your code that changes data.
After reading this post, you've hopefully realized just how simple it is to create applications that react to data changes using MongoDB Change Streams. Questions? Comments? Head over to our Developer Community to continue the conversation!

Copy Link
facebook icontwitter iconlinkedin icon
Rate this quickstart
star-empty
star-empty
star-empty
star-empty
star-empty
Related
Article

An Update on MongoDB's Ongoing Commitment to Swift


May 12, 2022
News & Announcements

Goodbye NSPredicate, hello Realm Swift Query API


Oct 19, 2022
Tutorial

Continuously Building and Hosting our Swift DocC Documentation using Github Actions and Netlify


May 10, 2022
Article

Making SwiftUI Previews Work For You


Oct 19, 2022
Table of Contents
  • Running the example code