Models and Connecting
Objectives
By the end of this lesson, you should be able to:
- Turn a Mongoose schema into a usable model
- Connect Mongoose to a real MongoDB database
- Perform basic CRUD through a Mongoose model instead of the native driver
๐ก Why this matters: A schema alone (last lesson) doesn’t talk to a database. This lesson turns it into a model, the object every query in the rest of this course actually calls.
โ ๏ธ 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.
Project File Structure
mongoose-intro/
โโโ package.json
โโโ .env
โโโ models/
โ โโโ Student.js
โโโ index.js
Connecting to MongoDB
// index.js
require('dotenv').config();
const mongoose = require('mongoose');
async function main() {
await mongoose.connect(process.env.MONGODB_URI);
console.log('Connected to MongoDB with Mongoose!');
}
main();
# .env
MONGODB_URI=mongodb://localhost:27017/school
node index.js
Connected to MongoDB with Mongoose!
mongoose.connect() is the Mongoose equivalent of Module 7’s MongoClient.connect(), and follows the same environment-variable pattern from Module 1, Lesson 5, the connection string lives in .env, never hard-coded.
Creating a Model
// models/Student.js
const mongoose = require('mongoose');
const studentSchema = new mongoose.Schema({
name: { type: String, required: true },
grade: { type: Number, required: true }
});
module.exports = mongoose.model('Student', studentSchema);
mongoose.model('Student', studentSchema) registers the model under the name 'Student', and, by convention, Mongoose stores its documents in a MongoDB collection named students, lowercased and pluralized automatically, the same naming convention Prisma uses for migrated tables (Module 4).
Using the Model
// index.js
require('dotenv').config();
const mongoose = require('mongoose');
const Student = require('./models/Student');
async function main() {
await mongoose.connect(process.env.MONGODB_URI);
const student = await Student.create({ name: 'Erin', grade: 9 });
console.log(student);
const all = await Student.find();
console.log(all);
await mongoose.connection.close();
}
main();
{
_id: new ObjectId('65f1a2b3c4d5e6f7a8b9c0d1'),
name: 'Erin',
grade: 9,
__v: 0
}
[
{
_id: new ObjectId('65f1a2b3c4d5e6f7a8b9c0d1'),
name: 'Erin',
grade: 9,
__v: 0
}
]
Student.create() and Student.find() read noticeably closer to Prisma’s prisma.student.create() and prisma.student.findMany() than to the native driver’s students.insertOne() and students.find().toArray(), this is exactly the convenience an ORM/ODM layer adds. The __v field is Mongoose’s own internal version key, used for tracking document revisions, safe to ignore for now.
Try It
- Create a
models/Product.jsfile, define a schema, and export a model withmongoose.model('Product', productSchema). - Connect to MongoDB with
mongoose.connect(), using a connection string from.env. - Create a document with
Product.create(), and read it back withProduct.find(). - Explain, in your own words, what collection name Mongoose would use for a model named
Order.
Recap
mongoose.model(name, schema)turns a schema into a model, Mongoose derives the actual MongoDB collection name automatically (lowercased, pluralized).mongoose.connect()takes a connection string, loaded from.env, exactly like every other database connection in this course.- A Mongoose model’s methods (
create,find, and more) read close to Prisma Client’s API, both sit on top of a lower-level driver doing the actual work.
Next lesson: validation, rejecting bad data before it ever reaches the database.