How to set default values in Mongoose

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

Introduction

When building applications that persist data in MongoDB using Mongoose, it is oftentimes necessary to define default values for your schema to ensure the integrity and consistency of your dataset. This tutorial will guide you through the process of setting default values for Mongoose schemas, using the latest JavaScript syntax and the expressive capabilities of ES6 and beyond. We’ll start with the basics and gradually move to more advanced use cases, demonstrating the power of Mongoose’s default value feature.

Before diving in, it’s important to ensure that you have a Node.js environment set up with Mongoose installed. This tutorial assumes you have a working knowledge of Node.js and MongoDB, as well as familiarity with async/await and arrow functions for cleaner and more readable asynchronous code.

Setting up a Basic Default Value

Defaults in Mongoose schemas are a foundational feature that allow you to specify what value a document should have for a certain field if none was provided. This is particularly useful for fields that should have a defined value even when a new document is created without explicit parameters.

const mongoose = require('mongoose');
const { Schema } = mongoose;

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

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

(async () => {
  const newUser = new User({ name: 'John Doe' });
  await newUser.save();
  console.log(newUser);
})();

In the code snippet above, the ‘createdAt’ field will automatically be assigned the current date and time when a new User document is created, if none is provided.

Custom Functions for Dynamic Defaults

Default values are not limited to static values; you can also assign functions to dynamically determine the default value based on conditions during the creation of a new document. Below shows how you can use this capability.

const userSchema = new Schema({
  name: String,
  signUpBonus: { type: Boolean, default: () => someCondition() }
});

function someCondition() {
  // Your condition logic returning a boolean
  return Math.random() > 0.5;
}

// When a new User instance is created, the signUpBonus field
// will evaluate someCondition() to determine its default value

Defaults with Sub-Documents in Mongoose

Mongoose schemas can also have sub-documents with their own default values. This is ideal for nested documents. Let’s see it with an example.

const addressSchema = new Schema({
  city: { type: String, default: 'Unknown' },
  country: { type: String, default: 'Unknown' }
});

const userSchema = new Schema({
  name: String,
  address: { type: addressSchema, default: () => ({}) }
});

// Upon creation of a User without an address specified,
// Mongoose will fill in the values from the addressSchema defaults

Handling Arrays with Default Values

When working with arrays, you can provide a default value that can be an array itself, optionally leveraging a function to compute the defaults.

const userSchema = new Schema({
  name: String,
  preferences: { type: [String], default: ['Default Preference'] }
});

// The preferences array will start with a single 'Default Preference' element
// if no preferences are provided when the User document is created.

Advanced Patterns: Default Values with Async Functions

For advanced use cases, you could even use asynchronous functions to retrieve default values from databases or other services, before assigning them to a schema filepath. Since performance implications come into the picture when calling external services or enabling complicated logic to run for defaults setup, be cautious when utilizing this technique.

const userSchema = new Schema({
  name: String,
  lastAccessed: { 
    type: Date, 
    default: async () => await getLastAccessedDate()
  }
});

async function getLastAccessedDate() {
  // Logic to get the last accessed date, potentially from an external service
}

Summary

This tutorial has provided a comprehensive guide on how to use default values in Mongoose models, starting with simple static defaults and progressing through to advanced asynchronous functions. Default values can greatly aid in maintaining data integrity and simplifying client code. However, it is important to consider the implications of using defaults, especially with more complex setup or external dependencies that could affect performance.

We covered expectations and knowledge prerequisites, which makes this tutorial the go-to guide whether you are starting out or looking to expand your understanding of Mongoose schema defaults. Armed with this information, you should feel more confident when designing and working with Mongoose schemas in your Node.js applications.