How to create multifield indices in Mongoose

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. It manages relationships between data, provides schema validation, and translates between objects in code and their representation in MongoDB. Indexing is a key feature to improve the performance of database operations, particularly search queries, which can be optimized using multifield (compound) indices. In MongoDB, an index can span more than one field, allowing for efficient queries that touch upon multiple data aspects. In this guide, you will learn how to create and manage multifield indices in Mongoose using modern JS/TS syntax.

Prerequisites

  • Basic understanding of Node.js and Mongoose.
  • A MongoDB database instance.
  • An existing Node.js application with Mongoose installed.

Creating a Simple Multifield Index

Let’s start by defining a schema:

import mongoose from 'mongoose';
const { Schema } = mongoose;

const userSchema = new Schema({
    username: String,
    email: String,
    createdAt: { type: Date, default: Date.now }
});

// Create multifield index
userSchema.index({username: 1, createdAt: -1});

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

Explanation:

  • The index() method adds a compound index to the fields username and createdAt.
  • The value 1 specifies an ascending index and -1 specifies a descending index.

Using Index Options

Mongoose also supports index options:

userSchema.index({ username: 1, email: 1 }, { unique: true });

This compound index enforces that each combination of username and email must be unique.

Invalidating Duplicates Across Multiple Fields

To automatically handle errors use asynchronous error trapping around your save operations:

const createUser = async (userData) => {
    try {
        const user = new User(userData);
        await user.save();
    } catch (error) {
        console.error('Error creating user:', error);
        // Handle the error appropriately
    }
};

Advanced Usage: Complex Multifield Index Conditions

More sophisticated indices can use conditions:

userSchema.index({ username: 1, 'profile.status': 1 }, { partialFilterExpression: { 'profile.status': { $exists: true } } });

This only creates an index on documents where the profile.status exists.

Index Administration

To ensure that indices are being created during start-up use:

mongoose.connection.on('open', function () {
    User.init().then(() => console.log('Indices are built or confirmed.'));
});

Benchmarking Queries

You should benchmark indexed queries to understand performance gains:

User.find({ username: 'john_doe', createdAt: { $gte: new Date('2021-01-01') } })
    .explain('executionStats')
    .then(stats => console.log(stats));

Comparing the execution stats, look for the reduction in the ‘totalKeysExamined’ and ‘totalDocsExamined’ numbers to measure the effectiveness of your index.

Conclusion

Understanding how to implement multifield indexing in Mongoose effectively elevates the performance of your applications making use of MongoDB. In the advanced realm of NoSQL databases, properly indexing is crucial to reaping the benefits of its schema-less nature without incurring performance degradation. We have learned the foundational knowledge of creating and administering multifield indices, while considering best practices such as index uniqueness, conditioned indices, and regularly monitoring query performances.