Skip to content
BackendDatabaseExpressJsMongoDBNodeJs

8. Mongoose ODM – Schema, Model, and Validation समझे 2026

April 30, 2026 18 min read

नमस्ते दोस्तों! 🙏
स्वागत है The Easy Master पर!

क्या तुमने कभी सोचा है – MongoDB mein data structure कैसे define करें? Validation कैसे लगाएं? Relationships कैसे बनाएं?

Mongoose एक ODM (Object Data Modeling) library है जो MongoDB और Node.js के बीच bridge का काम करता है। यह schema validation, type casting, relationships को easy बनाता है।

Mongoose ODM schema model validation Hindi में समझना बहुत जरूरी है क्योंकि:

  • MERN stack का heart है Mongoose
  • Schema validation – data consistency maintain करता है
  • Type casting – automatically data types convert करता है
  • Relationships – populate() से easy joins
  • Middleware – pre/post hooks for business logic

Aaj kya seekhoge?

TopicKya Seekhega?
Mongoose Kya Hai?ODM introduction
SchemaData structure define
ModelCollection ka blueprint
ValidationBuilt-in validators
CRUD OperationsCreate, Read, Update, Delete
Query Methodsfind, findOne, findById
Relationshipspopulate() se joins
Middlewarepre/post hooks
VirtualsComputed fields
IndexesPerformance optimization

Kya tumhe pata hai?
Mongoose automatic connection pooling करता है – multiple connections manage करने की जरूरत नहीं!

तो चलिए शुरू करते हैं – Mongoose ODM schema model validation Hindi सीखने का सफर! 🚀

Table of Contents

1. Mongoose Kya Hai? – Introduction

Mongoose ek ODM (Object Data Modeling) library है जो MongoDB और Node.js के बीच bridge का काम करता है.

Mongoose Features:

FeatureBenefit
SchemaDefine data structure
ValidationAuto data validation
Type CastingAutomatic type conversion
Query BuildingEasy MongoDB queries
MiddlewarePre/post hooks
RelationshipsPopulate references
PluginsReusable functionality

Basic Example:

Code
const mongoose = require('mongoose');

// 1. Define Schema
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
age: { type: Number, min: 18 }
});

// 2. Create Model
const User = mongoose.model('User', userSchema);

// 3. Create Document
const user = new User({ name: 'Vivek', email: 'vivek@example.com', age: 25 });
await user.save();

// 4. Query
const users = await User.find({ age: { $gt: 18 } });

Mongoose ODM schema model validation Hindi में हम सब कुछ detail में समझेंगे.

2. Mongoose vs Native Driver – Comparison

FeatureNative MongoDB DriverMongoose
Schema❌ No✅ Yes
Validation❌ Manual✅ Built-in
Type Casting❌ Manual✅ Automatic
Relationships❌ Manual✅ populate()
Middleware❌ No✅ pre/post hooks
Query BuilderBasicAdvanced
Plugins❌ No✅ Yes
Learning CurveMediumEasy

Native Driver Example:

Code
// ❌ No schema, no validation
const { MongoClient } = require('mongodb');
const client = new MongoClient('mongodb://localhost:27017');
await client.connect();
const db = client.db('mydb');
const users = db.collection('users');

// Any data can be inserted!
await users.insertOne({ name: 123 }); // No validation!

Mongoose Example:

Code
// ✅ Schema, validation, type safety
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true }
});

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

// Validation applied automatically!
await User.create({ name: 'Vivek', email: 'vivek@example.com' });

3. Installation & Setup

Step 1: Install Mongoose

Code
npm install mongoose

Step 2: Connect to MongoDB

Code
// config/database.js
const mongoose = require('mongoose');

const connectDB = async () => {
  try {
    const conn = await mongoose.connect(process.env.MONGODB_URI);
    console.log(`✅ MongoDB Connected: ${conn.connection.host}`);
    console.log(`📦 Database: ${conn.connection.name}`);
  } catch (error) {
    console.error(`❌ Error: ${error.message}`);
    process.exit(1);
  }
};

module.exports = connectDB;

Step 3: Connection Events

Code
mongoose.connection.on('connected', () => {
  console.log('Mongoose connected to MongoDB');
});

mongoose.connection.on('error', (err) => {
  console.log('Mongoose connection error:', err);
});

mongoose.connection.on('disconnected', () => {
  console.log('Mongoose disconnected');
});

// Graceful shutdown
process.on('SIGINT', async () => {
  await mongoose.connection.close();
  console.log('Mongoose disconnected through app termination');
  process.exit(0);
});

4. Schema – Data Structure Define Karna

Schema defines structure of documents in a collection.

Basic Schema:

Code
const userSchema = new mongoose.Schema({
  name: String,
  email: String,
  age: Number,
  isActive: Boolean
});

Advanced Schema with Options:

Code
const userSchema = new mongoose.Schema({
  // String field
  name: {
    type: String,
    required: [true, 'Name is required'],
    trim: true,
    minlength: [2, 'Name must be at least 2 characters'],
    maxlength: [50, 'Name cannot exceed 50 characters'],
    lowercase: true,
    uppercase: false,
    match: [/^[a-zA-Z]+$/, 'Name can only contain letters']
  },
  
  // Email with unique constraint
  email: {
    type: String,
    required: [true, 'Email is required'],
    unique: true,
    trim: true,
    lowercase: true,
    match: [
      /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/,
      'Please enter a valid email'
    ]
  },
  
  // Number with min/max
  age: {
    type: Number,
    min: [0, 'Age cannot be negative'],
    max: [120, 'Age cannot exceed 120'],
    validate: {
      validator: Number.isInteger,
      message: 'Age must be an integer'
    }
  },
  
  // Boolean with default
  isActive: {
    type: Boolean,
    default: true
  },
  
  // Date
  birthDate: {
    type: Date,
    default: Date.now
  },
  
  // Array of strings
  hobbies: [{
    type: String,
    trim: true,
    enum: ['coding', 'reading', 'gaming', 'sports']
  }],
  
  // Nested object (Subdocument)
  address: {
    street: {
      type: String,
      required: true
    },
    city: {
      type: String,
      required: true
    },
    pincode: {
      type: Number,
      required: true,
      min: 100000,
      max: 999999
    },
    country: {
      type: String,
      default: 'India'
    }
  },
  
  // ObjectId reference to another collection
  createdBy: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  },
  
  // Mixed type (any data)
  metadata: {
    type: mongoose.Schema.Types.Mixed,
    default: {}
  },
  
  // Map
  settings: {
    type: Map,
    of: String,
    default: {}
  }
}, {
  timestamps: true, // Adds createdAt and updatedAt
  toJSON: { virtuals: true },
  toObject: { virtuals: true }
});

5. Schema Data Types – String, Number, Date etc.

Complete Data Types Reference:

TypeDescriptionExample
StringUTF-8 string{ type: String }
NumberNumber (integer or float){ type: Number }
DateDate object{ type: Date, default: Date.now }
Booleantrue/false{ type: Boolean, default: false }
ArrayArray of values[{ type: String }]
ObjectIdMongoDB ObjectId{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }
MixedAny type{ type: mongoose.Schema.Types.Mixed }
MapKey-value pairs{ type: Map, of: String }
Decimal128High precision decimal{ type: mongoose.Schema.Types.Decimal128 }
BufferBinary data{ type: Buffer }

Examples:

Code
const productSchema = new mongoose.Schema({
  // String with validation
  name: {
    type: String,
    required: true,
    trim: true
  },
  
  // Number with min/max
  price: {
    type: Number,
    required: true,
    min: 0,
    max: 1000000
  },
  
  // Date with default
  createdAt: {
    type: Date,
    default: Date.now,
    immutable: true
  },
  
  // Array of objects
  reviews: [{
    user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
    rating: { type: Number, min: 1, max: 5 },
    comment: String,
    createdAt: { type: Date, default: Date.now }
  }],
  
  // Map for dynamic keys
  attributes: {
    type: Map,
    of: String,
    default: {}
  },
  
  // Mixed for flexible data
  metadata: mongoose.Schema.Types.Mixed,
  
  // Decimal for currency
  tax: {
    type: mongoose.Schema.Types.Decimal128,
    default: 0.18
  }
});

6. Model – Collection Ka Blueprint

Model schema का compiled version है – collection ke saath interact karने के लिए.

Creating Model:

Code
const User = mongoose.model('User', userSchema);
// MongoDB collection name will be 'users' (plural, lowercase)

Model Methods:

Code
// CRUD methods
User.create(data)           // Insert document
User.find(filter)           // Find multiple
User.findOne(filter)        // Find one
User.findById(id)           // Find by _id
User.findByIdAndUpdate()    // Find by id and update
User.findByIdAndDelete()    // Find by id and delete
User.updateOne()            // Update one
User.updateMany()           // Update many
User.deleteOne()            // Delete one
User.deleteMany()           // Delete many
User.countDocuments()       // Count documents
User.exists()               // Check if exists

Model Instance Methods:

Code
const user = new User({ name: 'Vivek', email: 'vivek@example.com' });
await user.save(); // Save to database
await user.updateOne(); // Update this document
await user.deleteOne(); // Delete this document

7. Built-in Validators – required, min, max, enum

Required Validator:

Code
name: {
  type: String,
  required: [true, 'Name is required']  // Custom error message
}

String Validators:

Code
name: {
  type: String,
  required: true,
  enum: ['admin', 'user', 'moderator'],  // Only these values allowed
  match: /^[a-zA-Z]+$/,                   // Regex pattern
  minlength: [2, 'Too short'],
  maxlength: [50, 'Too long'],
  lowercase: true,                         // Convert to lowercase
  uppercase: false,                        // Convert to uppercase
  trim: true                              // Remove whitespace
}

Number Validators:

Code
age: {
  type: Number,
  min: [0, 'Age cannot be negative'],
  max: [120, 'Age cannot exceed 120']
},

price: {
  type: Number,
  min: 0,
  max: 1000000
}

Date Validators:

Code
birthDate: {
  type: Date,
  min: '1900-01-01',
  max: Date.now()
}

Array Validators:

Code
hobbies: {
  type: [String],
  validate: {
    validator: function(v) {
      return v && v.length > 0;
    },
    message: 'At least one hobby is required'
  }
}

8. Custom Validation – Apna Validator Likho

Custom Validator Function:

Code
const userSchema = new mongoose.Schema({
  email: {
    type: String,
    required: true,
    validate: {
      validator: async function(email) {
        // Check if email already exists
        const existingUser = await this.constructor.findOne({ email });
        return !existingUser;
      },
      message: 'Email already exists'
    }
  },
  
  password: {
    type: String,
    required: true,
    validate: {
      validator: function(v) {
        // Password must contain at least one number and one letter
        return /^(?=.*[A-Za-z])(?=.*\d)/.test(v);
      },
      message: 'Password must contain at least one letter and one number'
    }
  },
  
  website: {
    type: String,
    validate: {
      validator: function(v) {
        return /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/.test(v);
      },
      message: props => `${props.value} is not a valid URL!`
    }
  }
});

Multiple Validators:

Code
phone: {
  type: String,
  validate: [
    {
      validator: function(v) {
        return /^\d{10}$/.test(v);
      },
      message: 'Phone number must be 10 digits'
    },
    {
      validator: async function(v) {
        const user = await this.constructor.findOne({ phone: v });
        return !user;
      },
      message: 'Phone number already exists'
    }
  ]
}

Custom Validator with Options:

Code
age: {
  type: Number,
  required: true,
  validate: {
    validator: function(v) {
      return v >= 18 && v <= 60;
    },
    message: 'Age must be between 18 and 60',
    type: 'user-defined'
  }
}

9. CRUD Operations – Create, Read, Update, Delete

CREATE (Insert):

Code
// Method 1: Using new + save()
const user = new User({
name: 'Vivek',
email: 'vivek@example.com',
age: 25
});
const savedUser = await user.save();

// Method 2: Using create()
const user = await User.create({
name: 'Vivek',
email: 'vivek@example.com',
age: 25
});

// Method 3: insertMany() for multiple
const users = await User.insertMany([
{ name: 'User1', email: 'user1@test.com' },
{ name: 'User2', email: 'user2@test.com' }
]);

READ (Find):

Code
// Find all
const users = await User.find();

// Find with filter
const activeUsers = await User.find({ isActive: true });

// Find one
const user = await User.findOne({ email: 'vivek@example.com' });

// Find by ID
const user = await User.findById('65f1a2b3c4d5e6f7g8h9i0j1');

// With projection (select fields)
const users = await User.find({}, 'name email -_id');

// With sorting
const users = await User.find().sort({ age: -1 });

// With pagination
const users = await User.find()
.skip(10)
.limit(5);

UPDATE (Modify):

Code
// Update one
await User.updateOne(
{ email: 'vivek@example.com' },
{ $set: { age: 26, city: 'Mumbai' } }
);

// Update many
await User.updateMany(
{ isActive: true },
{ $set: { status: 'active' } }
);

// Find by ID and update
const user = await User.findByIdAndUpdate(
'65f1a2b3c4d5e6f7g8h9i0j1',
{ age: 26 },
{ new: true, runValidators: true }
);

// Increment
await User.updateOne(
{ _id: userId },
{ $inc: { loginCount: 1 } }
);

// Add to array
await User.updateOne(
{ _id: userId },
{ $push: { hobbies: 'reading' } }
);

DELETE (Remove):

Code
// Delete one
await User.deleteOne({ email: 'old@example.com' });

// Delete many
await User.deleteMany({ isActive: false });

// Find by ID and delete
const user = await User.findByIdAndDelete(userId);

// Delete all
await User.deleteMany({});

10. Query Methods – find, findOne, findById

Query Builder Methods:

Code
// Chainable queries
const users = await User
.find({ isActive: true })
.where('age').gte(18).lte(60)
.select('name email age')
.sort({ age: -1 })
.limit(10)
.skip(0)
.lean();

// Count documents
const count = await User.countDocuments({ isActive: true });

// Check if exists
const exists = await User.exists({ email: 'vivek@example.com' });

// Distinct values
const cities = await User.distinct('address.city');

Comparison Operators:

Code
// $eq (equal)
User.find({ age: { $eq: 25 } })

// $ne (not equal)
User.find({ age: { $ne: 25 } })

// $gt (greater than)
User.find({ age: { $gt: 18 } })

// $gte (greater or equal)
User.find({ age: { $gte: 18 } })

// $lt (less than)
User.find({ age: { $lt: 60 } })

// $lte (less or equal)
User.find({ age: { $lte: 60 } })

// $in (in array)
User.find({ city: { $in: ['Mumbai', 'Delhi'] } })

// $nin (not in array)
User.find({ city: { $nin: ['Mumbai'] } })

Logical Operators:

Code
// $or
User.find({
  $or: [
    { age: { $gt: 30 } },
    { city: 'Mumbai' }
  ]
})

// $and
User.find({
  $and: [
    { age: { $gte: 18 } },
    { age: { $lte: 60 } }
  ]
})

// $nor
User.find({
  $nor: [
    { isActive: false },
    { age: { $lt: 18 } }
  ]
})

11. Relationships – populate() Se Joins

Defining References:

Code
// User Schema
const userSchema = new mongoose.Schema({
  name: String,
  email: String
});

// Post Schema with reference to User
const postSchema = new mongoose.Schema({
  title: String,
  content: String,
  author: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User',
    required: true
  },
  likes: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  }],
  comments: [{
    user: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'User'
    },
    text: String,
    createdAt: { type: Date, default: Date.now }
  }]
});

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

Using populate():

Code
// Basic populate
const posts = await Post.find()
  .populate('author', 'name email')
  .populate('likes', 'name');

// Populate nested fields
const posts = await Post.find()
  .populate({
    path: 'comments.user',
    select: 'name avatar'
  });

// Deep populate
const posts = await Post.find()
  .populate({
    path: 'author',
    populate: {
      path: 'profile',
      select: 'bio avatar'
    }
  });

// Populate with conditions
const posts = await Post.find()
  .populate({
    path: 'comments.user',
    match: { isActive: true },
    select: 'name'
  });

12. Middleware – pre/post Hooks

Pre Middleware (Before Operation):

Code
// Hash password before saving
userSchema.pre('save', async function(next) {
  if (!this.isModified('password')) return next();
  
  try {
    const salt = await bcrypt.genSalt(10);
    this.password = await bcrypt.hash(this.password, salt);
    next();
  } catch (error) {
    next(error);
  }
});

// Update timestamps before update
userSchema.pre('findOneAndUpdate', function(next) {
  this.set({ updatedAt: new Date() });
  next();
});

// Validate email domain
userSchema.pre('validate', function(next) {
  if (this.email && !this.email.endsWith('@example.com')) {
    next(new Error('Only example.com emails are allowed'));
  } else {
    next();
  }
});

// Log before delete
userSchema.pre('deleteOne', { document: true, query: false }, function(next) {
  console.log(`Deleting user: ${this.name}`);
  next();
});

Post Middleware (After Operation):

Code
// Log after save
userSchema.post('save', function(doc, next) {
  console.log(`New user created: ${doc.email}`);
  next();
});

// Cleanup after delete
userSchema.post('findOneAndDelete', async function(doc) {
  if (doc) {
    await Post.deleteMany({ author: doc._id });
    console.log(`Deleted user ${doc.email} and their posts`);
  }
});

// Error handling
userSchema.post('save', function(error, doc, next) {
  if (error.name === 'MongoError' && error.code === 11000) {
    next(new Error('Email must be unique'));
  } else {
    next(error);
  }
});

13. Virtuals – Computed Fields

Virtuals fields that are not stored in database – computed properties.

Basic Virtual:

Code
const userSchema = new mongoose.Schema({
  firstName: String,
  lastName: String,
  birthDate: Date
});

// Getter virtual
userSchema.virtual('fullName').get(function() {
  return `${this.firstName} ${this.lastName}`;
});

// Setter virtual
userSchema.virtual('fullName').set(function(value) {
  const [firstName, lastName] = value.split(' ');
  this.firstName = firstName;
  this.lastName = lastName;
});

// Age from birth date
userSchema.virtual('age').get(function() {
  if (!this.birthDate) return null;
  const ageDiff = Date.now() - this.birthDate.getTime();
  const ageDate = new Date(ageDiff);
  return Math.abs(ageDate.getUTCFullYear() - 1970);
});

// Enable virtuals in output
userSchema.set('toJSON', { virtuals: true });
userSchema.set('toObject', { virtuals: true });

Virtual for Relationships:

Code
// User Schema
const userSchema = new mongoose.Schema({
  name: String
});

// Post Schema
const postSchema = new mongoose.Schema({
  title: String,
  authorId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
});

// Virtual populate
userSchema.virtual('posts', {
  ref: 'Post',
  localField: '_id',
  foreignField: 'authorId'
});

// Usage
const user = await User.findById(userId).populate('posts');

14. Indexes – Performance Optimization

Creating Indexes:

Code
const userSchema = new mongoose.Schema({
  name: String,
  email: { type: String, unique: true }, // Unique index automatically
  age: Number,
  city: String,
  createdAt: Date
});

// Single field index
userSchema.index({ email: 1 });

// Compound index (multiple fields)
userSchema.index({ city: 1, age: -1 });

// Text index for search
userSchema.index({ name: 'text', bio: 'text' });

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

// Partial index (only active users)
userSchema.index(
  { age: 1 },
  { partialFilterExpression: { isActive: true } }
);

// TTL index (auto delete after 30 days)
userSchema.index(
  { createdAt: 1 },
  { expireAfterSeconds: 2592000 }
);

Index Options:

Code
userSchema.index({ email: 1 }, {
  unique: true,
  name: 'email_unique_idx',
  background: true,
  sparse: true,
  expireAfterSeconds: 3600
});

15. Complete Example – User API

Complete User Model:

Code
// models/User.js
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');

const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: [true, 'Name is required'],
    trim: true,
    minlength: [2, 'Name must be at least 2 characters'],
    maxlength: [50, 'Name cannot exceed 50 characters']
  },
  email: {
    type: String,
    required: [true, 'Email is required'],
    unique: true,
    trim: true,
    lowercase: true,
    match: [
      /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/,
      'Please enter a valid email'
    ]
  },
  password: {
    type: String,
    required: [true, 'Password is required'],
    minlength: [6, 'Password must be at least 6 characters'],
    select: false
  },
  age: {
    type: Number,
    min: [0, 'Age cannot be negative'],
    max: [120, 'Age cannot exceed 120']
  },
  role: {
    type: String,
    enum: ['user', 'admin', 'moderator'],
    default: 'user'
  },
  isActive: {
    type: Boolean,
    default: true
  },
  lastLogin: {
    type: Date
  },
  address: {
    street: String,
    city: String,
    pincode: Number,
    country: { type: String, default: 'India' }
  },
  preferences: {
    type: Map,
    of: String,
    default: {}
  }
}, {
  timestamps: true,
  toJSON: { virtuals: true },
  toObject: { virtuals: true }
});

// Indexes
userSchema.index({ email: 1 });
userSchema.index({ role: 1, isActive: 1 });
userSchema.index({ createdAt: -1 });

// Virtual for full address
userSchema.virtual('fullAddress').get(function() {
  const { street, city, pincode, country } = this.address;
  return `${street}, ${city} - ${pincode}, ${country}`;
});

// Pre-save middleware: hash password
userSchema.pre('save', async function(next) {
  if (!this.isModified('password')) return next();
  
  try {
    const salt = await bcrypt.genSalt(10);
    this.password = await bcrypt.hash(this.password, salt);
    next();
  } catch (error) {
    next(error);
  }
});

// Instance method: compare password
userSchema.methods.comparePassword = async function(candidatePassword) {
  return await bcrypt.compare(candidatePassword, this.password);
};

// Instance method: update last login
userSchema.methods.updateLastLogin = async function() {
  this.lastLogin = new Date();
  return await this.save();
};

// Static method: find active users
userSchema.statics.findActiveUsers = function() {
  return this.find({ isActive: true });
};

// Query helper
userSchema.query.byRole = function(role) {
  return this.where({ role });
};

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

module.exports = User;

Using the Model:

Code
// controllers/userController.js
const User = require('../models/User');

// Create user
const createUser = async (req, res) => {
  try {
    const user = await User.create(req.body);
    res.status(201).json({ success: true, data: user });
  } catch (error) {
    res.status(400).json({ success: false, error: error.message });
  }
};

// Get users
const getUsers = async (req, res) => {
  try {
    const users = await User.findActiveUsers()
      .byRole('user')
      .sort('-createdAt')
      .limit(10);
    res.json({ success: true, data: users });
  } catch (error) {
    res.status(500).json({ success: false, error: error.message });
  }
};

// Login
const login = async (req, res) => {
  try {
    const { email, password } = req.body;
    
    const user = await User.findOne({ email }).select('+password');
    if (!user) {
      return res.status(401).json({ error: 'Invalid credentials' });
    }
    
    const isMatch = await user.comparePassword(password);
    if (!isMatch) {
      return res.status(401).json({ error: 'Invalid credentials' });
    }
    
    await user.updateLastLogin();
    
    res.json({ success: true, data: { id: user.id, name: user.name, email: user.email } });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};

16. Common Mistakes + Solutions

Mistake 1: Not using new keyword for schema

Code
// ❌ Missing new keyword
const userSchema = mongoose.Schema({ name: String });

// ✅ Use new keyword
const userSchema = new mongoose.Schema({ name: String });

Mistake 2: Forgetting await with save()

Code
// ❌ Missing await
user.save(); // Returns promise, not executed properly

// ✅ Use await
await user.save();

Mistake 3: Not handling validation errors

Code
// ❌ No error handling
const user = await User.create(data);

// ✅ Handle validation errors
try {
  const user = await User.create(data);
} catch (error) {
  if (error.name === 'ValidationError') {
    // Handle validation errors
  }
}

Mistake 4: Not using select for sensitive fields

Code
// ❌ Password returned in queries
const user = await User.findById(id); // Includes password!

// ✅ Exclude password by default
password: { type: String, select: false }

// ✅ Or explicitly exclude
const user = await User.findById(id).select('-password');

17. Quick Cheat Sheet

Schema Types:

Code
String, Number, Date, Boolean, Array, ObjectId, Mixed, Map, Buffer, Decimal128

Common Validators:

Code
required: true,
unique: true,
min: 0, max: 100,
minlength: 2, maxlength: 50,
enum: ['a', 'b'],
match: /regex/,
trim: true,
lowercase: true

CRUD Methods:

OperationMethod
CreateModel.create(data)
Read AllModel.find(filter)
Read OneModel.findById(id)
UpdateModel.findByIdAndUpdate(id, data)
DeleteModel.findByIdAndDelete(id)

Query Helpers:

Code
.where('age').gte(18)
.select('name email')
.sort('-createdAt')
.limit(10)
.skip(20)
.lean()
.populate('field')

18. FAQ

Q1: Mongoose ODM schema model validation Hindi में सबसे important kya hai?
Schema definition – ye data structure और validation define करता है.

Q2: Schema vs Model – kya antar hai?
Schema defines structure, Model provides interface to interact with collection.

Q3: create() vs save() – kya antar hai?
create() directly model par call होता है, save() document instance पर.

Q4: Validation kab run hoti hai?
save(), create(), updateOne() with runValidators: true, findByIdAndUpdate() with runValidators: true.

Q5: populate() kya karta hai?
References को actual documents से replace करता है (MongoDB joins).

Q6: Virtual fields kya hote hain?
Fields that are not stored in DB – computed properties के लिए.

Q7: Middleware kya hai?
pre/post hooks – save, validate, remove से पहले/बाद code run करने के लिए.

Q8: lean() kyun use karein?
Mongoose documents के बजाय plain JavaScript objects return करता है – faster queries.

Q9: Index kyun banayein?
Query performance improve करने के लिए – frequently queried fields पर index banाएं.

Q10: select: false kya karta hai?
Field को by default queries से exclude करता है (passwords, tokens के लिए).

19. Conclusion

बहुत बढ़िया दोस्तों! आज हमने Mongoose ODM schema model validation Hindi को पूरी detail में समझा.

Quick Recap:

ConceptKey Takeaway
SchemaDefine data structure
ModelCollection interface
ValidationBuilt-in + custom validators
Relationshipspopulate() for joins
Middlewarepre/post hooks
VirtualsComputed fields
IndexesPerformance optimization

Mera personal experience:

Mongoose use करने से पहले main native driver use करता था – validation और relationships handle करना मुश्किल था। Mongoose ने development bohot fast कर दिया. Schema validation से data quality improve हुई.

Tum bhi ye steps follow karo:

  1. ✅ Schema define करो
  2. ✅ Validators add करो
  3. ✅ Model create करो
  4. ✅ CRUD operations implement करो
  5. ✅ Indexes add करो

अब तुम्हारी बारी है!

नीचे comment में बताओ:

  1. तुम Mongoose use karoge ya native driver?
  2. कौन सा validator सबसे useful लगा?
  3. अगला topic क्या चाहिए? (Mongoose Validation Deep Dive? Aggregation? Transactions?)

The Easy Master पर बने रहो। Happy Coding with Mongoose! 🚀🍃

Resources

Additional Resources

TheEasyMaster

Author at The Easy Master.

Related posts

Leave a Reply

Your email address will not be published. Required fields are marked *