Defining Schemas
Objectives
By the end of this lesson, you should be able to:
- Explain what Mongoose adds on top of the native driver
- Define a schema with field types, required fields, and default values
- Explain how a Mongoose schema compares to a Prisma model
💡 Why this matters: Module 7’s native driver works, but nothing stops a document from missing a required field, or having a field of the wrong type. Mongoose adds structure back, the closest thing MongoDB has in this course to Prisma’s
schema.prisma.
⚠️ A note on verification: as throughout the MongoDB half of this course, this tooling has no route to a local MongoDB server. The code below reflects Mongoose’s stable, current, documented API. Try it yourself, on your own machine, against a real MongoDB server.
Installing Mongoose
npm install mongoose
Mongoose wraps the native mongodb driver, connecting still happens through a MongoDB connection string, no separate database to install.
Defining a Schema
const mongoose = require('mongoose');
const studentSchema = new mongoose.Schema({
name: { type: String, required: true },
grade: { type: Number, required: true },
email: { type: String },
active: { type: Boolean, default: true },
enrolledAt: { type: Date, default: Date.now }
});
Reading it field by field, next to what each corresponds to from earlier in this course:
| Mongoose | Meaning | Prisma equivalent (Module 4) |
|---|---|---|
type: String, required: true |
A required text field | name String |
type: Number, required: true |
A required numeric field | grade Int |
type: String (no required) |
An optional text field | email String? |
default: true |
A default value | @default(true) |
default: Date.now |
A default timestamp | @default(now()) |
Field Types
Mongoose’s core types: String, Number, Boolean, Date, Array, and ObjectId (a reference to another document, covered in Module 9). Each is written as the type in a field’s definition, as shown above.
Nested Objects
Since MongoDB documents can nest data directly (Module 7, Lesson 1), a schema can too:
const studentSchema = new mongoose.Schema({
name: { type: String, required: true },
grade: { type: Number, required: true },
contact: {
email: { type: String },
phone: { type: String }
}
});
contact becomes a nested object on every document, { name: 'Erin', grade: 9, contact: { email: 'erin@example.com' } }, no separate table or JOIN needed, exactly the nesting introduced conceptually in Module 7.
Arrays of Values
const studentSchema = new mongoose.Schema({
name: { type: String, required: true },
clubs: [String]
});
clubs: [String] allows any number of strings, { name: 'Jordan', clubs: ['chess', 'robotics'] }.
Try It
- Define a schema for a
Productwithname(required string),price(required number), andinStock(boolean, defaulting totrue). - Add a nested
dimensionsobject withwidthandheightfields. - Add a
tagsfield that accepts an array of strings. - Compare your schema field by field against what the equivalent Prisma
modelblock (Module 4) would look like.
Recap
- A Mongoose schema defines field types, which fields are required, and default values, the closest MongoDB equivalent to a Prisma
modelblock. - Nested objects and arrays can be declared directly in a schema, matching MongoDB’s own flexible document structure.
- Nothing has connected to a database yet, that, and turning this schema into a usable model, is the next lesson.
Next lesson: creating a Mongoose model from this schema, and connecting it to a real database.