How to auto-generate timestamps in Mongoose

Updated: December 30, 2023 By: Guest Contributor Post a comment

Overview

Automatically generating timestamps is a common requirement in application development, capable of providing valuable insights into when a document was created or last modified within a database. Mongoose, a MongoDB object modeling tool designed for asynchronous environments such as Node.js, streamlines the process of working with MongoDB and includes functionality for this very purpose. This tutorial will cover how to auto-generate timestamps in Mongoose using the latest JavaScript and Node.js syntax.

Setting Up

Before we delve into timestamps, make sure you have Node.js and MongoDB installed on your system. Begin by initializing a new Node.js project with:

npm init -y

Then install Mongoose:

npm install mongoose

Basic Mongoose Schema with Timestamps

The most basic use case involving timestamps is to ‘auto-generate’ them within a Mongoose schema; Every new instance will have ‘createdAt’ and ‘updatedAt’ fields automatically. Here’s how:

import mongoose from 'mongoose';

const userSchema = new mongoose.Schema({
  username: String
}, { timestamps: true });

const User = mongoose.model('User', userSchema);

Now, whenever you create a new User document, Mongoose will add createdAt and updatedAt fields containing timestamps of creation and last modification times, respectively.

Customizing Timestamps

If you’d like to customize the names of your timestamp fields, you can do so easily:

const customUserSchema = new mongoose.Schema({
  username: String
}, {
  timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
});

const CustomUser = mongoose.model('CustomUser', customUserSchema);

Advanced Usage: Middleware and Manual Timestamps

Sometimes, automated timestamps aren’t flexible enough, and you may need to manipulate them manually using Mongoose middlewares, also known as hooks:

userSchema.pre('save', function(next) {
  if (this.isNew) {
    this.created_at = new Date();
  } else if (this.isModified()) {
    this.updated_at = new Date();
  }
  next();
});

This code uses the pre hook to manually set created_at and updated_at before saving the document to the database.

Using Virtuals for Derived Timestamps

Mongoose virtuals allow you to define fields that Mongoose does not persist to MongoDB. These are useful for derived properties. Consider the following example, where we create a ‘timeSinceCreation’ virtual:

userSchema.virtual('timeSinceCreation').get(function() {
  return Date.now() - this.created_at.getTime();
});

You can then access the ‘timeSinceCreation’ property, which will calculate the time elapsed since the user was created.

Handling Timestamps with Nested Schemas

Moving towards a more advanced scenario, consider handling documents that contain subdocuments. Each subdocument can also have its own timestamps, like so:

const postSchema = new mongoose.Schema({
  title: String,
  content: String,
  comments: [{
    text: String,
    timestamps: true
  }]
}, {
  timestamps: true
});

Here, both your posts and individual comments inside posts will have their own pairs of timestamps.

Error Handling with Async/Await and Timestamps

Mongoose operations often necessitate excellent error handling, especially when dealing with asynchronous code. Let’s use async/await:

const createUser = async (userData) => {
  try {
    const user = await User.create(userData);
    console.log('User created with timestamps:', user);
  } catch (error) {
    console.error('Error creating user:', error);
  }
};

The above function responsibly creates a user and logs their timestamps, while also catching any errors that might occur during the process.

Conclusion

To auto-generate timestamps in Mongoose effectively, opting for the inbuilt Mongoose timestamps option is usually the best starting point. Conveniently defining, customizing, or even manipulating timestamps through middleware offers a flexible solution capable of satisfying most needs. With these capabilities and the powerful asynchronous support Node.js offers, Mongoose handles the temporal dimensions of your application data with assurance and elegance, clearing your path to focus on delivering the best user experience possible.