In applications involving time-sensitive data, having a mechanism to automatically expire and remove documents can be incredibly useful. In MongoDB, this functionality is provided with TTL (Time To Live) indexes, which can be utilized in Mongoose, a popular MongoDB object modeling tool for Node.js. Here’s a complete guide on how to leverage TTL in your Mongoose schemas for automatic document expiration.
Introduction
Mongoose provides a high-level schema-based solution to model your application data and includes built-in type casting, validation, query building, and business logic hooks. One lesser-known but powerful feature of Mongoose is the ability to set a TTL on documents — a document will be automatically deleted from the collection when the specified Time To Live (TTL) elapses after its creation or a specified timestamp.
This feature is extremely useful for certain types of data that only need to persist for a certain time frame, such as session data or temporary caches. By automatically expiring data, you can reduce the overhead of manually cleaning up old data and ensure that your database does not hold onto unnecessary information indefinitely.
Setting up the Environment
Before diving into the setup, it is assumed that you have Node.js/npm installed and set up on your system. Start by initializing a new Node.js project and installing mongoose:
const express = require('express');
const mongoose = require('mongoose');
const app = express();
mongoose.connect('mongodb://localhost/testdb', {useNewUrlParser: true, useUnifiedTopology: true});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
We also need to create a suitable Mongoose Model. In the example, our Schema will be for a collection named Event which will hold documents that should expire after some time.
Basic TTL Setting
A TTL index on a Mongoose schema can be set on a Date type path. It tells MongoDB how long to keep documents in the collection. When the specified time elapses, MongoDB watches and automatically deletes these documents.
const eventSchema = new mongoose.Schema({
title: String,
createdAt: { type: Date, default: Date.now, index: {expires: '2h'} }
});
const Event = mongoose.model('Event', eventSchema);
This simple expires option specifies that each document should expire 2 hours after the createdAt field value. Note that the createdAt default value is set to the current server time when a document is created.
In-depth TTL Configuration
Sometimes you need more control over the expiration behavior. You can specify a different Date which becomes the base point from which the TTL is calculated. Mongoose lets you define this pivot dynamically when creating a new Event document or by utilizing schema methods.
eventSchema.methods.setExpiryDate = function(hours) {
this.createdAt = new Date(Date.now() + hours * 60 * 60 * 1000);
};
const myEvent = new Event({title: 'Special Sale'});
myEvent.setExpiryDate(5); // This particular event will expire after 5 hours.
myEvent.save();
This flexibility can be especially valuable for applications that require different documents to have various TTLs.
Advanced Usage
There may also be scenarios where an application needs to adjust TTL dynamically or based on some other conditions than the time of document creation. Mongoose’s middleware and query functions provide opportunities for sophisticated control over expiration.
eventSchema.pre('save', function(next) {
if(this.isNew) {
this.setExpiryDate(3); // Set default TTL for new document
}
next();
});
eventSchema.methods.extendExpiry = function(extensionHours) {
const newExpireTime = new Date(this.createdAt.getTime() + extensionHours * 60 * 60 * 1000);
if (newExpireTime > this.createdAt) {
this.createdAt = newExpireTime;
this.save();
}
};
Here, a save middleware is introduced to provide a default TTL for new documents and extendExpiry method is exposed to alter the expiration point beyond its initial setting programmatically.
Conclusion
Exploiting Mongoose’s flexibility to set document expiration dates with TTL can help manage data more elegantly, increase the efficiency of your database, and keep it clean from old remnants. This tutorial walked you through setting a simple TTL on Mongoose Schema paths and explored more complex setups for controlling time-sensitive data. Using these techniques, you can construct a database strategy that evolves with the necessity of your data’s lifespan.