HomeLearnArticleRealm Triggers Treats and Tricks - Auto Increment a Running ID Field

Realm Triggers Treats and Tricks - Auto Increment a Running ID Field

Published: Jun 17, 2021

  • Atlas
  • Realm
  • JavaScript
  • ...

By Pavel Duchovny

Rate this article

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 showcase an auto increment of a running ID in a collection similar to relational database sequence use. A sequence in relational databases like Oracle or SqlServer lets you use it to maintain a running ID for your table rows.

If we translate this into a students collection example, we would like to get the studentId field auto incremented.

1{
2 studentId : 1,
3 studentName : "Mark Olsen",
4 age : 15,
5 phone : "+1234546789",
6},
7{
8 studentId : 2,
9 studentName : "Peter Parker",
10 age : 17,
11 phone : "+1234546788",
12}

I wanted to share an interesting solution based on triggers, and throughout this article, we will use a students collection example with studentsId field to explain the discussed approach.

#Prerequisites

Of course, an initial step will be to verify we 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

The main flow of the auto-increment trigger concept
The main flow of the auto-increment trigger concept

There are three main components that allow our auto increment mechanisim to function.

#1. Define a Source Collection

We should pick the collection that we need the auto increment to work upon (students) and we can define a unique index on that field. This is not a must but it makes sense:

1db.students.createIndex({studentsId : 1}, {unique : true});

#2. Define a Generic Function to Auto Increment the ID

In order for us to resuse the auto increment code for more than one collection, I've decided to build a generic function and later associate it with the relevant triggers. Let's call the function autoIncrement. This function will receive an "insert" event from the source collection and increments a helper counters collection document that stores the current counter per collection. It uses findOneAndUpdate to return an automatically incremented value per the relevant source namespace, using the _id as the namespace identifier. Once retrieved, the source collection is being set with a generic field called <COLLECTION_NAME>Id (in this example, studentsId).

1exports = async function(changeEvent) {
2
3 // Source document _id
4 var docId = changeEvent.fullDocument._id;
5
6 // Get counter and source collection instances
7 const counterCollection = context.services.get("<ATLAS-SERVICE>").db(changeEvent.ns.db).collection("counters");
8 const targetCollection = context.services.get("<ATLAS-SERVICE>").db(changeEvent.ns.db).collection(changeEvent.ns.coll);
9
10 // automically increment and retrieve a relevant sequence relevant to the current namespace (db.collection)
11 var counter = await counterCollection.findOneAndUpdate({_id: changeEvent.ns },{ $inc: { seq_value: 1 }}, { returnNewDocument: true, upsert : true});
12
13 // Set a generic field <COLLECTIONP_NAME>Id
14 var doc = {};
15 doc[`${changeEvent.ns.coll}Id`] = counter.seq_value;
16 var updateRes = await targetCollection.updateOne({_id : docId},{ $set : doc});
17
18 console.log(`Updated ${JSON.stringify(changeEvent.ns)} with counter ${counter.seq_value} result : ${JSON.stringify(updateRes)}`);
19};

Important: Please replace <ATLAS-SERVICE> with your linked service. The default value is "mongodb-atlas" if you only have one cluster linked to your Realm application and you didn't change it.

Please note that when we query and increment the counter, we expect to get the new version of the document returnNewDocument: true and upsert : true in case this is the first document.

The "counter" collection document after the first run on our student collection will look like this:

1{
2 _id : {
3 db : "app",
4 coll : "students"
5 },
6 seq_value : 1
7}

#3. Building the Trigger on Insert Operation and Associating it with Our Generic Function

Now let's define our trigger based on our Atlas cluster service and our database and source collection, in my case, app.students.

Please make sure to select "Event Ordering" toggled to "ON" and the "insert" operation.

Trigger configuration on students collection

Now let's associate it with our pre-built function: autoIncrement.

Trigger configuration on students collection

Once we will insert our document into the collection, it will be automatically updated with a running unique number for studentsId.

Outcome of the students collection

#Wrap-Up

With the presented technique, we can leverage triggers to auto increment and populate id fields. This may open your mind to other ideas to design your next flows on MongoDB Realm.

Please look out for my next article in this series where we will use triggers to auto-translate our documents and benefit Atlas Search multilingual abilities.

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.

Rate this article

More from this series

Triggers Tricks and Treats
  • Realm Triggers Treats and Tricks - Document-Based Trigger Scheduling
  • Realm Triggers Treats and Tricks - Auto Increment a Running ID Field
  • Triggers Treats and Tricks: Cascade Document Delete Using Triggers Preimage
MongoDB Icon
  • Developer Hub
  • Documentation
  • University
  • Community Forums

© MongoDB, Inc.