All Articles
Tech News9 min read

MongoDB for Backend Developers: Beyond CRUD Operations

Master MongoDB with aggregation pipelines, indexing strategies, and schema design patterns used in production applications.

T

TechGyanic

December 12, 2025

MongoDB for Backend Developers

I spent my first year with MongoDB treating it like SQL with a different syntax. That was wrong. MongoDB shines when you embrace its document model properly.

Document Schema Design

Embedding vs Referencing

Embed when:

  • Data is accessed together
  • Child data is bounded (< 100 items)
  • Updates are infrequent
// Embedded - User with addresses
{
  _id: ObjectId("..."),
  name: "Vikram Singh",
  email: "[email protected]",
  addresses: [
    { type: "home", city: "Mumbai", pincode: "400001" },
    { type: "office", city: "Mumbai", pincode: "400051" }
  ]
}

Reference when:

  • Data grows unbounded
  • Many-to-many relationships
  • Data accessed independently
// Referenced - Order with products
// orders collection
{
  _id: ObjectId("..."),
  userId: ObjectId("user_id"),
  products: [
    { productId: ObjectId("prod_1"), quantity: 2 },
    { productId: ObjectId("prod_2"), quantity: 1 }
  ],
  total: 2500
}

// products collection (separate)
{
  _id: ObjectId("prod_1"),
  name: "Wireless Mouse",
  price: 800
}

Aggregation Pipeline

The real power of MongoDB:

// Sales analytics example
db.orders.aggregate([
  // Stage 1: Filter last 30 days
  {
    $match: {
      createdAt: { $gte: new Date(Date.now() - 30*24*60*60*1000) }
    }
  },
  // Stage 2: Group by product
  {
    $unwind: "$products"
  },
  // Stage 3: Calculate totals
  {
    $group: {
      _id: "$products.productId",
      totalQuantity: { $sum: "$products.quantity" },
      totalRevenue: { $sum: { $multiply: ["$products.quantity", "$products.price"] } },
      orderCount: { $sum: 1 }
    }
  },
  // Stage 4: Sort by revenue
  {
    $sort: { totalRevenue: -1 }
  },
  // Stage 5: Get top 10
  {
    $limit: 10
  }
]);

Indexing Strategies

Performance lives or dies by indexing:

// Single field index
db.users.createIndex({ email: 1 });

// Compound index (order matters!)
db.orders.createIndex({ userId: 1, createdAt: -1 });

// Text index for search
db.products.createIndex({ name: "text", description: "text" });

// Partial index (only index active users)
db.users.createIndex(
  { email: 1 },
  { partialFilterExpression: { isActive: true } }
);

Checking Index Usage

db.orders
  .find({ userId: "123", status: "pending" })
  .explain("executionStats");

Look for IXSCAN (good) vs COLLSCAN (bad, full collection scan).

Transactions

Yes, MongoDB supports ACID transactions:

const session = client.startSession();
try {
  session.startTransaction();
  
  await accounts.updateOne(
    { _id: fromAccountId },
    { $inc: { balance: -amount } },
    { session }
  );
  
  await accounts.updateOne(
    { _id: toAccountId },
    { $inc: { balance: amount } },
    { session }
  );
  
  await session.commitTransaction();
} catch (error) {
  await session.abortTransaction();
  throw error;
} finally {
  session.endSession();
}

Performance Tips

  1. Use projection - Only fetch fields you need
  2. Limit results - Always paginate large collections
  3. Avoid $where - Write native queries instead
  4. Use bulk operations - For multiple writes
// Bulk write example
const ops = users.map(user => ({
  updateOne: {
    filter: { _id: user._id },
    update: { $set: { lastLogin: new Date() } }
  }
}));

await db.users.bulkWrite(ops);

MongoDB is fast when used correctly, slow when treated like SQL. Learn its strengths.

mongodbdatabasenosqlbackendnodejs
Share this article
T

Written by

TechGyanic

Sharing insights on technology, software architecture, and development best practices.