skills/doanchienthangdev/omgkit/Developing with MongoDB

Developing with MongoDB

SKILL.md

Developing with MongoDB

Quick Start

// Schema with Mongoose
import mongoose, { Schema, Document } from 'mongoose';

interface IUser extends Document {
  email: string;
  profile: { firstName: string; lastName: string };
  createdAt: Date;
}

const userSchema = new Schema<IUser>({
  email: { type: String, required: true, unique: true, lowercase: true },
  profile: {
    firstName: { type: String, required: true },
    lastName: { type: String, required: true },
  },
}, { timestamps: true });

userSchema.index({ email: 1 });
export const User = mongoose.model<IUser>('User', userSchema);

Features

Feature Description Guide
Document Schema Type-safe schema design with Mongoose Embed related data, use references for large collections
CRUD Operations Create, read, update, delete with type safety Use findById, findOne, updateOne, deleteOne
Aggregation Pipelines Complex data transformations and analytics Chain $match, $group, $lookup, $project stages
Indexing Query optimization with proper indexes Create compound indexes matching query patterns
Transactions Multi-document ACID operations Use sessions for operations requiring atomicity
Change Streams Real-time data change notifications Watch collections for inserts, updates, deletes

Common Patterns

Repository Pattern with Pagination

async findPaginated(filter: FilterQuery<IUser>, page = 1, limit = 20) {
  const [data, total] = await Promise.all([
    User.find(filter).sort({ createdAt: -1 }).skip((page - 1) * limit).limit(limit),
    User.countDocuments(filter),
  ]);
  return { data, pagination: { page, limit, total, totalPages: Math.ceil(total / limit) } };
}

Aggregation Pipeline

const stats = await Order.aggregate([
  { $match: { status: 'completed', createdAt: { $gte: startDate } } },
  { $group: { _id: '$userId', total: { $sum: '$amount' }, count: { $sum: 1 } } },
  { $sort: { total: -1 } },
  { $limit: 10 },
]);

Transaction for Order Creation

const session = await mongoose.startSession();
try {
  session.startTransaction();
  await Product.updateOne({ _id: productId }, { $inc: { stock: -quantity } }, { session });
  const order = await Order.create([{ userId, items, total }], { session });
  await session.commitTransaction();
  return order[0];
} catch (error) {
  await session.abortTransaction();
  throw error;
} finally {
  session.endSession();
}

Best Practices

Do Avoid
Design schemas based on query patterns Embedding large arrays in documents
Create indexes for frequently queried fields Using $where or mapReduce in production
Use lean() for read-only queries Skipping validation on writes
Implement pagination for large datasets Storing large files directly (use GridFS)
Set connection pool size appropriately Hardcoding connection strings
Use transactions for multi-document ops Ignoring index usage in explain plans
Add TTL indexes for expiring data Creating too many indexes (write overhead)
Weekly Installs
0
GitHub Stars
3
First Seen
Jan 1, 1970