Mongoose
Enum
JavaScript
MongoDB
Tutorial

How to Create and Use Enum in Mongoose

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Mongoose is a powerful ODM (Object Data Modeling) library for MongoDB and Node.js, providing a straightforward schema-based solution to model application data. One of the common requirements when modeling data is the need to specify certain fields to have one of a select set of values. Enumerations (enums) provide an elegant way to achieve this in Mongoose. This article will delve into how to create and use enums with Mongoose, complete with technical explanations and practical examples.

Setting Up Mongoose

To begin, ensure you have Mongoose installed in your project. If not, you can install it via npm:

bash
npm install mongoose

Next, connect to your MongoDB database:

javascript
1const mongoose = require("mongoose");
2
3mongoose.connect("mongodb://localhost:27017/mydatabase", {
4  useNewUrlParser: true,
5  useUnifiedTopology: true,
6});
7
8const db = mongoose.connection;
9db.on("error", console.error.bind(console, "connection error:"));
10db.once("open", () => {
11  console.log("Connected to the database");
12});

Creating an Enum in Mongoose

Enums in Mongoose are declared using the enum property in a schema definition. The enum field can accept an array of allowed values for that particular attribute.

Basic Example

Consider a simple case where you want to define a schema for 'UserRole' with a specific set of allowed roles: 'admin', 'user', and 'guest'.

javascript
1const userSchema = new mongoose.Schema({
2  name: String,
3  role: {
4    type: String,
5    enum: ["admin", "user", "guest"],
6    required: true,
7  },
8});
9
10const User = mongoose.model("User", userSchema);

Here, the role field can only have one of the three specified values. Any attempt to save a document with a role outside these values will result in an error.

Comprehensive Example

Let's consider a more detailed example where we have a task management system, and each task can have a specific status: 'pending', 'in_progress', 'done'.

javascript
1const taskSchema = new mongoose.Schema({
2  title: {
3    type: String,
4    required: true,
5  },
6  description: String,
7  status: {
8    type: String,
9    enum: ["pending", "in_progress", "done"],
10    default: "pending",
11  },
12  assignedTo: {
13    type: mongoose.Schema.Types.ObjectId,
14    ref: "User",
15  },
16});
17
18const Task = mongoose.model("Task", taskSchema);

In this schema:

  • The status field is constrained to one of the specified values using enum.
  • The default option is used to automatically assign 'pending' status for new tasks when not explicitly specified.

Validations and Error Handling

When a specified field's value does not match any of the values in the enum list, Mongoose triggers a validation error. Handling these errors is crucial for maintaining data integrity.

Example of Validation Error Handling

javascript
1const newTask = new Task({
2  title: "Design Homepage",
3  status: "completed", // Invalid status
4});
5
6newTask.save((err) => {
7  if (err) {
8    console.error("Error:", err.errors.status.message);
9  } else {
10    console.log("Task saved successfully");
11  }
12});

In this example, saving the task triggers a validation error because 'completed' is not an allowed status. The validation error can be captured and logged accordingly.

Enum with TypeScript and Mongoose

If your project uses TypeScript, you can further enhance type safety by defining a TypeScript enum alongside your Mongoose schema.

typescript
1enum UserRole {
2  Admin = "admin",
3  User = "user",
4  Guest = "guest",
5}
6
7interface IUser {
8  name: string;
9  role: UserRole;
10}
11
12const userSchema = new mongoose.Schema<IUser>({
13  name: { type: String, required: true },
14  role: {
15    type: String,
16    enum: Object.values(UserRole),
17    required: true,
18  },
19});
20
21const User = mongoose.model<IUser>("User", userSchema);

Here, the UserRole TypeScript enum ensures only valid values are passed to or returned from the schema.

Conclusion

Using enums in Mongoose is a powerful way to enforce data constraints and validate inputs, ensuring robust application logic. Whether you're using standard JavaScript or TypeScript, Mongoose's enums allow you to maintain clean and error-resistant code while interacting with MongoDB.

Summary Table

FeatureDescription
enum in MongooseLimits field values to a set of predefined options
Basic Enum ExampleRole: ['admin', 'user', 'guest']
Advanced Enum ExampleTask Status: ['pending', 'in_progress', 'done']
Default OptionAutomatically assigns a default value if not provided
ValidationEnsures data integrity, triggers errors if values are outside definition
TypeScript SupportEnhances type safety with TypeScript enums

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.