NoCache

Table of Contents

Auto Delete Expired Documents in MongoDB with Node.js (TTL Index)

Cyrus Kao
Last modified on .

TTL Indexes in MongoDB are very useful for storing data like logs or user sessions. The document will remove itself after a certain amount of time which is specified by the index. This tutorial will be done in both JavaScript and TypeScript using Node.js with node-mongodb-native, which is the official MongoDB Node.js driver.

Install MongoDB Node.js Driver

Install node-mongodb-native from NPM:

$ npm i mongodb

Connect to MongoDB

Connect to the MongoDB server and select the database:

  • JavaScript

    const MongoClient = require('mongodb').MongoClient;
    
    async function init() {
    	const Client = await MongoClient.connect('mongodb://127.0.0.1:27017'); // change it to the address your MongoDB is listening on
    	const Database = Client.db('MyDatabase'); // change it to the database name of your choice
    }
    Javascript
  • TypeScript

    import { MongoClient } from 'mongodb';
    
    async function init() {
    	const Client = await MongoClient.connect('mongodb://127.0.0.1:27017'); // change it to the address your MongoDB is listening on
    	const Database = Client.db('MyDatabase'); // change it to the database name of your choice
    }
    TypeScript

Make sure the MongoDB daemon is up and running in the background while connecting.

Create/Select Collection

Select a collection, it'll create itself if it does not exist:

  • JavaScript

    ...
    async function init() {
    	...
    	const Collection = Database.collection('MyCollection'); // change it to the collection name of your choice
    }
    Javascript
  • TypeScript

    ...
    interface Collection_MyCollection {
    	date: Date;
    	msg: string;
    } // create a interface specifying the type of the document
    
    async function init() {
    	...
    	const Collection = Database.collection<Collection_MyCollection>('MyCollection'); // change it to the collection name of your choice
    }
    TypeScript

Create TTL (Time-To-Live) Index

Create a TTL index on the collection:

...
async function init() {
	...
	await Collection.createIndex({
		date: 1, // 1 for ascending, -1 for descending
	}, {
		expireAfterSeconds: 60 * 60 * 24, // expire after 24 hours
	}); // documents will expire after 24 hours relative to the field `date`
}
Javascript

The field you specify should be in type Date, otherwise it won't work.

Try It Out

We'll create a function called printDocuments to print out the documents in the collection, and insert two documents with the current date and day before to see if they expire correctly:

...
async function init() {
	...
	async function printDocuments() {
		console.log(await Collection.find({}).toArray()); // print all documents in the collection
	}

	await Collection.insertOne({
		date: new Date(), // today
		msg: 'this won\'t expire soon',
	});

	await Collection.insertOne({
		date: new Date(Date.now() - 60 * 60 * 24 * 1000), // yesterday
		msg: 'this will expire soon',
	});

	printDocuments();

	setTimeout(() => {
		printDocuments();
	}, 60 * 2 * 1000); // since MongoDB only performs deletion every 60 seconds, we'll check the documents after 2 minutes
}

init(); // execute the function
Javascript
[
	{
		_id: new ObjectId("6203411f91c0d03dffa77509"),
		date: 2022-02-09T04:20:47.313Z,
		msg: "this won't expire soon"
	},
	{
		_id: new ObjectId("6203411f91c0d03dffa7750a"),
		date: 2022-02-08T04:20:47.317Z,
		msg: 'this will expire soon'
	}
]
Output
[
	{
		_id: new ObjectId("6203411f91c0d03dffa77509"),
		date: 2022-02-09T04:20:47.313Z,
		msg: "this won't expire soon"
	}
]
Output

Be aware that MongoDB runs the background task that removes expired documents every 60 seconds, so there will be a short period of delay before the expired documents get deleted.

Official documentation
Official documentation of MongoDB

If the document didn't get deleted, verify the index is created correctly:

Indexes
Indexes on MongoDB Compass

Full Example

A full example including above steps:

  • JavaScript

    const MongoClient = require('mongodb').MongoClient;
    
    async function init() {
    	const Client = await MongoClient.connect('mongodb://127.0.0.1:27017');
    	const Database = Client.db('MyDatabase');
    	const Collection = Database.collection('MyCollection');
    
    	await Collection.createIndex({
    		date: 1,
    	}, {
    		expireAfterSeconds: 60 * 60 * 24,
    	});
    
    	async function printDocuments() {
    		console.log(await Collection.find({}).toArray());
    	}
    
    	await Collection.insertOne({
    		date: new Date(),
    		msg: 'this won\'t expire soon',
    	});
    
    	await Collection.insertOne({
    		date: new Date(Date.now() - 60 * 60 * 24 * 1000),
    		msg: 'this will expire soon',
    	});
    
    	printDocuments();
    
    	setTimeout(() => {
    		printDocuments();
    	}, 60 * 2 * 1000);
    }
    
    init();
    Javascript
  • TypeScript

    import { MongoClient } from 'mongodb';
    
    interface Collection_MyCollection {
    	date: Date;
    	msg: string;
    }
    
    async function init() {
    	const Client = await MongoClient.connect('mongodb://127.0.0.1:27017');
    	const Database = Client.db('MyDatabase');
    	const Collection = Database.collection<Collection_MyCollection>('MyCollection');
    
    	await Collection.createIndex({
    		date: 1,
    	}, {
    		expireAfterSeconds: 60 * 60 * 24,
    	});
    
    	async function printDocuments() {
    		console.log(await Collection.find({}).toArray());
    	}
    
    	await Collection.insertOne({
    		date: new Date(),
    		msg: 'this won\'t expire soon',
    	});
    
    	await Collection.insertOne({
    		date: new Date(Date.now() - 60 * 60 * 24 * 1000),
    		msg: 'this will expire soon',
    	});
    
    	printDocuments();
    
    	setTimeout(() => {
    		printDocuments();
    	}, 60 * 2 * 1000);
    }
    
    init();
    TypeScript

Comments

Sign in to leave a comment.