CodeHive
open main menu
Product Catalog API Visualization
Part of series: MongoDB Roadmap

Mini Project: Building a Lightning Fast Product API

/ 2 min read

Welcome to the end of Week 2! 🏎️

We’ve learned about:

  • Single Field Indexes
  • Compound Indexes & ESR Rule
  • Multikey Indexes
  • Explain Plans

Today, we apply this to a real-world scenario: E-Commerce Search.

1. The Requirement

We need an API endpoint GET /products that supports:

  • Filtering by Category (Equality)
  • Filtering by Price Range (Range)
  • Sorting by Rating (Sort)
  • Sorting by Creation Date (Sort)

AND it must respond in under 50ms for 1 million products.

2. The Data Model

{
  "_id": ObjectId("..."),
  "name": "Gaming Laptop",
  "category": "Electronics",
  "price": 1200,
  "rating": 4.5,
  "tags": ["gaming", "computer"], // Array
  "createdAt": ISODate("...")
}

3. The Queries & Indexes

Scenario A: Filter by Category, Sort by Price

db.products.find({ category: "Electronics" }).sort({ price: 1 })

Strategy (ESR):

  • E: category
  • S: price
  • R: -

Index Needed: { category: 1, price: 1 }

Scenario B: Filter by Category AND Rating > 4

db.products.find({ category: "Electronics", rating: { $gt: 4 } })

Strategy (ESR):

  • E: category
  • S: -
  • R: rating

Index Needed: { category: 1, rating: 1 }

Scenario C: Filter by Category, Sort by Date, Price < 500

db.products.find({ category: "Electronics", price: { $lt: 500 } }).sort({ createdAt: -1 })

Strategy (ESR):

  • E: category
  • S: createdAt
  • R: price

Index Needed: { category: 1, createdAt: -1, price: 1 }


4. The “One Index to Rule Them All”

We can’t create 50 indexes. Let’s try to cover most bases with Two Compound Indexes.

Index 1: The Browser { category: 1, rating: -1, price: 1 } Good for: “Show me Electronics, sorted by best rating, then cheapest.”

Index 2: The Newest Items { category: 1, createdAt: -1 } Good for: “Show me the newest Electronics.”

5. Implementation in Node.js

const getProducts = async (req, res) => {
  const { category, minPrice, sortBy } = req.query;
  const filter = {};
  const sort = {};

  // E - Equality
  if (category) filter.category = category;

  // R - Range
  if (minPrice) filter.price = { $gte: Number(minPrice) };

  // S - Sort
  if (sortBy === 'newest') sort.createdAt = -1;
  else if (sortBy === 'rating') sort.rating = -1;

  // Execute
  const products = await db.collection('products')
    .find(filter)
    .sort(sort)
    .limit(20)
    .toArray();

  res.json(products);
};

6. Week 2 Wrap Up

You now know how to stop the COLLSCAN. You know that { a: 1, b: 1 } is NOT the same as { b: 1, a: 1 }. You are ready to handle millions of documents.

Next Week: Week 3 - The Aggregation Framework! 📊 We will stop doing find() and start building complex data pipelines!

Have a great weekend! 🌞


Next Step

Next: Aggregation Basics →