Mongoose: Auto add createdAt and updatedAt timestamps

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

Introduction

Mongoose is a powerful Object Data Modeling (ODM) library for MongoDB and Node.js that manages relationships between data, provides schema validation, and translates between objects in code and their representation in MongoDB. One common requirement in applications is keeping track of when a document was created and last updated. This tutorial demonstrates how to automatically add createdAt and updatedAt timestamps to your Mongoose schemas using built-in schema options and custom middleware.

Enabling Timestamps in Schema

Mongoose provides an easy way to enable automatic management of createdAt and updatedAt fields in your schemas via the timestamps schema option. Here’s how you can do it:

import mongoose from 'mongoose';

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

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

With the above schema, Mongoose will automatically add createdAt and updatedAt fields to the User documents upon creation and update these fields respectively whenever the documents are modified.

Customizing Field Names

If you want to customize the names of the timestamp fields, you can set the timestamps option to an object specifying the field names:

const userSchema = new mongoose.Schema({
  // fields
}, {
  timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
});

This will result in timestamp fields named created_at and updated_at instead.

Advanced Timestamps Customization

If the default behavior of the timestamp does not fit your needs, or you need to add more complex logic to the setting of these fields, you can use Mongoose middleware (pre and post hooks).

userSchema.pre('save', function (next) {
  const now = new Date();
  this.updatedAt = now;
  if (!this.createdAt) {
    this.createdAt = now;
  }
  next();
});

userSchema.pre('updateOne', function (next) {
  this.set({ updatedAt: new Date() });
  next();
});

userSchema.pre('findOneAndUpdate', function (next) {
  this.set({ updatedAt: new Date() });
  next();
});

With these middleware functions, specifically, the pre-save hook checks if the createdAt field has not been set before and updates the updatedAt field, whereas the pre-updateOne and pre-findOneAndUpdate hooks ensure that the updatedAt field is updated on each respective operation.

Dealing with Nested Schemas

Oftentimes, your mongoose documents will contain nested schemas. To ensure timestamps are correctly managed in those as well, you can enable timestamps in the nested schemas separately:

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

const productSchema = new mongoose.Schema({
  name: String,
  reviews: [reviewSchema]
}, {
  timestamps: true
});

This will add createdAt and updatedAt fields both to the Product documents and each review subdocument.

Error Handling

While enabling and customizing timestamps is often straightforward, developers should also handle possible errors gracefully. For instance, always check for possible errors during database operations.

const saveUser = async (userData) => {
  const newUser = new User(userData);
  try {
    await newUser.save();
    return newUser;
  } catch (error) {
    console.error('Error saving user:', error);
    throw error;
  }
};

Indexing Timestamps

Another advanced topic is indexing your timestamp fields for performance enhancements, especially if you often query documents based on creation or modification dates.

userSchema.index({ createdAt: 1 });
userSchema.index({ updatedAt: 1 });

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

These indexes will speed up sorting and querying operations based on the timestamp fields.

Summary

In this tutorial, we’ve covered how to effortlessly integrate automatic timestamps in Mongoose schemas for Node.js applications. We’ve looked at how to apply decent naming conventions and enable advanced customization options, setup of nested schemas timestamps, the importance of error handling, and indexing timestamp fields for performance optimization. Tracking document creation and update times is crucial for many applications, and Mongoose makes this process seamless. With these techniques, you’re well-equipped to handle timestamps in your next Node.js project backed by Mongoose and MongoDB.