Explore Developer Center's New Chatbot! MongoDB AI Chatbot can be accessed at the top of your navigation to answer all your MongoDB questions.

MongoDB Developer
Atlas
plus
Sign in to follow topics
MongoDB Developer Centerchevron-right
Developer Topicschevron-right
Productschevron-right
Atlaschevron-right

Realm Triggers Treats and Tricks - Document-Based Trigger Scheduling

Pavel Duchovny5 min read • Published Dec 20, 2021 • Updated Sep 09, 2024
Atlas
Facebook Icontwitter iconlinkedin icon
Rate this article
star-empty
star-empty
star-empty
star-empty
star-empty
Some features mentioned below will be deprecated on Sep. 30, 2025. Learn more.
In this blog series, we are trying to inspire you with some reactive Realm trigger use cases. We hope these will help you bring your application pipelines to the next level.
Essentially, triggers are components in our Atlas projects/Realm apps that allow a user to define a custom function to be invoked on a specific event.
  • Database triggers: We have triggers that can be scheduled based on database events—like deletes, inserts, updates, and replaces—called database triggers.
  • Scheduled triggers: We can schedule a trigger based on a cron expression via scheduled triggers.
  • Authentication triggers: These triggers are only relevant for Realm authentication. They are triggered by one of the Realm auth providers' authentication events and can be configured only via a Realm application.
For this blog post, I would like to focus on trigger scheduling patterns.
Let me present a use case and we will see how the discussed mechanics might help us in this scenario. Consider a meeting management application that schedules meetings and as part of its functionality needs to notify a user 10 minutes before the meeting.
How would we create a trigger that will be fired 10 minutes before a timestamp which is only known by the "meeting" document?
First, let's have a look at the meetings collection documents example:
1{
2 _id : ObjectId("5ca4bbcea2dd94ee58162aa7"),
3 event : "Mooz Meeting",
4 eventDate : ISODate("2021-03-20:14:00:00Z"),
5 meetingUrl : "https://mooz.meeting.com/5ca4bbcea2dd94ee58162aa7",
6 invites : ["jon.doe@myemail.com", "doe.jonas@myemail.com"]
7 }
I wanted to share an interesting solution based on triggers, and throughout this article, we will use a meeting notification example to explain the discussed approach.

Prerequisites

First, verify that you have an Atlas project with owner privileges to create triggers.
If you haven't yet set up your free cluster on MongoDB Atlas, now is a great time to do so. You have all the instructions in this blog post.

The Idea Behind the Main Mechanism

I will use the event example as a source document initiating the flow with an insert to a meetings collection:
1{
2 _id : ObjectId("5ca4bbcea2dd94ee58162aa7"),
3 event : "Mooz Meeting",
4 eventDate : ISODate("2021-03-20:11:00:00Z"),
5 meetingUrl : "https://mooz.meeting.com/5ca4bbcea2dd94ee58162aa7"
6 invites : ["jon.doe@example.com"],
7 phone : "+123456789"
8}
Once we insert this document into the meetings collection, it will create the following record in a helper collection called notifications using an insert trigger:
1{
2 _id : ObjectId("5ca4bbcea2dd94ee58162aa7"),
3 triggerDate : ISODate("2021-03-10:50:00:00Z")
4}
The time and _id are calculated from the source document and aim to fire once 2021-03-10:50:00:00Z arrives via a fireScheduleTasks trigger. This trigger is based on a delete operation out of a TTL index on the triggerDate field from the notifications.
This is when the user gets the reminder!
On a high level, here is the flow described above.
A meeting document is tracked by a trigger, creating a notification document. This document at the specified time will cause a delete event. The delete will fire a notification trigger to notify the user.
A meeting document is tracked by a trigger, creating a notification document. This document at the specified time will cause a delete event. The delete will fire a notification trigger to notify the user.
There are three main components that allow our system to trigger based on our document data.

1. Define a Notifications Helper Collection

First, we need to prepare our notifications collection. This collection will be created implicitly by the following index creation command.
Now we will create a TTL index. This index will cause the schedule document to expire when the value in triggerDate field arrives at its expiry lifetime of 0 seconds after its value.
1db.notifications.createIndex( { "triggerDate": 1 }, { expireAfterSeconds: 0 } )

2. Building a Trigger to Populate the Schedule Collection

When setting up your scheduleTasks trigger, make sure you provide the following:
  1. Linked Atlas service and verify its name.
  2. The database and collection name we are basing the scheduling on, e.g., meetings.
  3. The relevant trigger operation that we want to schedule upon, e.g., when an event is inserted.
  4. Link it to a function that will perform the schedule collection population.
My trigger UI configuration to populate the scheduling collection.
My trigger UI configuration to populate the scheduling collection.
To populate the notifications collection with relevant triggering dates, we need to monitor our documents in the source collection. In our case, the user's upcoming meeting data is stored in the "meeting" collection with the userId field. Our trigger will monitor inserts to populate a Scheduled document.
1exports = function(changeEvent) {
2 // Get the notifications collection
3 const coll = context.services.get("<ATLAS-SERVICE>").db("<DATABASE>").collection("notifications");
4
5 // Calculate the "triggerDate" and populate the trigger collection and duplicate the _id
6 const calcTriggerDate = new Date(changeEvent.fullDocument.eventDate - 10 * 60000);
7 return coll.insertOne({_id:changeEvent.fullDocument._id,triggerDate: calcTriggerDate });
8};
Important: Please replace <ATLAS-SERVICE> and <DATABASE> with your linked service and database names.

3. Building the Trigger to Perform the Action on the "Trigger Date"

To react to the TTL "delete" event happening exactly when we want our scheduled task to be executed, we need to use an "on delete" database trigger I call fireScheduleTasks.
When setting up your fireScheduleTasks trigger, make sure you provide the following:
  1. Linked Atlas service and verify its name.
  2. The database and collection for the notifications collection, e.g., notifications.
  3. The relevant trigger operation that we want to schedule upon, which is "DELETE."
  4. Link it to a function that will perform the fired task.
Now that we have populated the notifications collection with the triggerDate, we know the TTL index will fire a "delete" event with the relevant deleted _id so we can act upon our task.
In my case, 10 minutes before the user's event starts, my document will reach its lifetime and I will send a text using Twilio service to the attendee's phone.
A prerequisite for this stage will be to set up a Twilio service using your Twilio cloud credentials.
  1. Make sure you have a Twilio cloud account with its SID and your Auth token.
  2. Set up the SID and Auth token into the Realm Twilio service configuration.
  3. Configure your Twilio Messaging service and phone number.
Once we have it in place, we can use it to send SMS notifications to our invites.
1exports = async function(changeEvent) {
2 // Get meetings collection
3 const coll = context.services.get("<ATLAS-SERVICE>").db("<DATABASE>").collection("meetings");
4
5 // Read specific meeting document
6 const doc = await coll.findOne({ _id: changeEvent.documentKey._id});
7
8 // Send notification via Twilio SMS
9 const twilio = context.services.get("<TWILIO-SERVICE>");
10 twilio.send({
11 to: doc.phone,
12 from: "+123456789",
13 body: `Reminder : Event ${doc.event} is about to start in 10min at ${doc.scheduledOn}`
14 });
15};
Important: Replace <ATLAS-SERVICE> and <DATABASE> with your linked service and database names.
That's how the event was fired at the appropriate time.

Wrap Up

With the presented technique, we can leverage existing triggering patterns to build new ones. This may open your mind to other ideas to design your next flows on MongoDB Realm.
In the following article in this series, we will learn how we can implement auto-increment with triggers.
If you have questions, please head to our developer community website where the MongoDB engineers and the MongoDB community will help you build your next big idea with MongoDB.

Facebook Icontwitter iconlinkedin icon
Rate this article
star-empty
star-empty
star-empty
star-empty
star-empty
Related
Tutorial

Unlocking Semantic Search: Building a Java-Powered Movie Search Engine with Atlas Vector Search and Spring Boot


Sep 18, 2024 | 10 min read
Tutorial

Flexible Querying With Atlas Search


Jul 12, 2024 | 3 min read
Tutorial

MongoDB Atlas With Terraform: Database Users and Vault


Apr 15, 2024 | 9 min read
Tutorial

Getting Started With Azure Spring Apps and MongoDB Atlas: A Step-by-Step Guide


Jan 27, 2024 | 5 min read
Table of Contents