Automatic Last Modified Field With MongoDB
MongoDB Realm is a great Firebase alternative that is backed by a “proper” database. I was missing automatic created_at
and last_modified_at
helpers from Django in a MongoDB project so I implemented them using triggers. Turns out it wasn’t as straightforward as I thought but still pretty simple in the end.
MongoDB Realm has very powerful triggers which are JavaScript functions that operate on a linked Atlas (a hosted MongoDB) cluster. The possibilities with these are almost limitless – you can even install your own npm packages! The only tricky part was to figure out a way to not fall into a forever loop when updating a document with a trigger that runs on every update.
AFAIK there isn’t a “this update was triggered by a trigger”-flag so you need to figure out the bail out condition manually. The following tigger function runs on insert, update and replace. It updates ’lastModifiedAt’ field in a document to current timestamp using $currentDate operator but only if lastModifiedAt
field is not updated in the changeEvent.
exports = function(changeEvent) {
const docId = changeEvent.documentKey._id;
const description = changeEvent.updateDescription;
const insertEvent = changeEvent.operationType === "insert";
if (!docId || (!insertEvent && !description)) { return; }
if (insertEvent || !Object.keys(description.updatedFields).includes("lastModifiedAt")) {
context.services
.get("my-cluster-name")
.db("my-db-name")
.collection("my-collection-name")
.updateOne(
{ _id: docId },
{ $currentDate: {lastModifiedAt: true} }
);
}
};
Adding automated created_at
field is much simpler; just run the trigger with insert events and you’re set. (Or, you can retrieve the same data without any extra work by using ObjectId.getTimestamp. I always like to have a dedicated field for this, hence a trigger.)