LearnThatStack Ace your next interview

MongoDB Technical.
Interview cheat sheet.

Quick reference for MongoDB Technical - sectioned for fast scanning. Skim the part you're shaky on, walk in confident.

Database Technologies 13-section reference ~9 min read

Summary

MongoDB is a document-oriented NoSQL database that stores data in flexible, JSON-like BSON format. It provides horizontal scaling through sharding, high availability through replica sets, and a rich query language with aggregation framework. Key features include schema flexibility, powerful indexing, ACID transactions (v4.0+), and built-in replication. Essential for applications requiring flexible schemas, real-time analytics, content management, and handling of semi-structured data at scale.

1. MongoDB Basics

What is MongoDB?

  • NoSQL database - Document-oriented, schema-less
  • Stores data in BSON (Binary JSON) format
  • Horizontal scaling through sharding
  • High availability through replica sets

Key Concepts

SQL MongoDB
Database Database
Table Collection
Row Document
Column Field
Index Index
JOIN $lookup / Embedded docs

Data Types

  • String, Number (int32, int64, double)
  • Boolean, Date, ObjectId
  • Array, Embedded Document
  • Binary Data, Null, RegEx

2. CRUD Operations

Create

// Insert one document
db.users.insertOne({ name: "John", age: 30 })

// Insert multiple documents
db.users.insertMany([
  { name: "Alice", age: 25 },
  { name: "Bob", age: 35 }
])

Read

// Find all
db.users.find()

// Find with filter
db.users.find({ age: { $gt: 25 } })

// Find one
db.users.findOne({ name: "John" })

// Projection (select fields)
db.users.find({}, { name: 1, age: 1, _id: 0 })

Update

// Update one
db.users.updateOne(
  { name: "John" },
  { $set: { age: 31 } }
)

// Update many
db.users.updateMany(
  { age: { $lt: 30 } },
  { $inc: { age: 1 } }
)

// Replace entire document
db.users.replaceOne(
  { name: "John" },
  { name: "John", age: 32, city: "NYC" }
)

Delete

// Delete one
db.users.deleteOne({ name: "John" })

// Delete many
db.users.deleteMany({ age: { $gt: 50 } })

3. Query Operators

Comparison Operators

$eq    // Equal
$ne    // Not equal
$gt    // Greater than
$gte   // Greater than or equal
$lt    // Less than
$lte   // Less than or equal
$in    // In array
$nin   // Not in array

// Example
db.users.find({ age: { $gte: 25, $lte: 35 } })
db.users.find({ status: { $in: ["active", "pending"] } })

Logical Operators

$and   // AND condition
$or    // OR condition
$not   // NOT condition
$nor   // NOR condition

// Example
db.users.find({
  $and: [
    { age: { $gte: 25 } },
    { status: "active" }
  ]
})

db.users.find({
  $or: [
    { age: { $lt: 20 } },
    { age: { $gt: 60 } }
  ]
})

Element Operators

$exists // Field exists
$type   // Field type

// Example
db.users.find({ email: { $exists: true } })
db.users.find({ age: { $type: "number" } })

Array Operators

$all       // All elements match
$elemMatch // At least one element matches
$size      // Array size

// Example
db.products.find({ tags: { $all: ["red", "large"] } })
db.orders.find({ items: { $elemMatch: { price: { $gt: 100 } } } })
db.users.find({ hobbies: { $size: 3 } })

Update Operators

$set       // Set field value
$unset     // Remove field
$inc       // Increment value
$push      // Add to array
$pull      // Remove from array
$addToSet  // Add unique to array
$pop       // Remove first/last from array

// Examples
db.users.updateOne(
  { _id: 1 },
  {
    $set: { status: "active" },
    $inc: { loginCount: 1 },
    $push: { tags: "premium" }
  }
)

4. Indexes

Types of Indexes

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

// Compound index
db.users.createIndex({ status: 1, createdAt: -1 })  // -1 = descending

// Text index
db.articles.createIndex({ content: "text" })

// 2dsphere index (geospatial)
db.locations.createIndex({ coordinates: "2dsphere" })

// TTL index (auto-delete after time)
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })

// Unique index
db.users.createIndex({ email: 1 }, { unique: true })

Index Management

// List indexes
db.users.getIndexes()

// Drop index
db.users.dropIndex({ email: 1 })

// Drop all indexes
db.users.dropIndexes()

5. Aggregation Framework

Basic Pipeline Stages

// Basic aggregation pipeline
db.orders.aggregate([
  { $match: { status: "completed" } },
  { $group: {
      _id: "$customerId",
      totalSpent: { $sum: "$amount" },
      orderCount: { $sum: 1 }
  }},
  { $sort: { totalSpent: -1 } },
  { $limit: 10 }
])

Common Pipeline Stages

$match     // Filter documents
$group     // Group by field(s)
$project   // Shape output
$sort      // Sort results
$limit     // Limit results
$skip      // Skip documents
$unwind    // Deconstruct array
$lookup    // Join collections
$count     // Count documents
$facet     // Multiple pipelines

// Example with $lookup (JOIN)
db.orders.aggregate([
  {
    $lookup: {
      from: "customers",
      localField: "customerId",
      foreignField: "_id",
      as: "customer"
    }
  },
  { $unwind: "$customer" }
])

Aggregation Operators

// Accumulator operators (use with $group)
$sum       // Sum values
$avg       // Average
$min       // Minimum
$max       // Maximum
$first     // First value
$last      // Last value
$push      // Create array

// Example
db.sales.aggregate([
  {
    $group: {
      _id: "$product",
      avgPrice: { $avg: "$price" },
      minPrice: { $min: "$price" },
      maxPrice: { $max: "$price" }
    }
  }
])

6. Data Modeling

Embedding vs Referencing

// Embedding (denormalized)
{
  _id: 1,
  name: "John",
  addresses: [
    { street: "123 Main", city: "NYC" },
    { street: "456 Oak", city: "LA" }
  ]
}

// Referencing (normalized)
// Users collection
{ _id: 1, name: "John", addressIds: [101, 102] }

// Addresses collection
{ _id: 101, street: "123 Main", city: "NYC" }
{ _id: 102, street: "456 Oak", city: "LA" }

Schema Design Patterns

  1. One-to-One: Embed or reference
  2. One-to-Many: Embed if few, reference if many
  3. Many-to-Many: Use array of references

Best Practices

  • Embed for data accessed together
  • Reference for large/growing subdocuments
  • Consider query patterns when designing
  • Avoid deep nesting (max 100 levels)

7. Transactions

ACID Properties

  • Atomicity: All or nothing
  • Consistency: Valid state transitions
  • Isolation: Concurrent operations don't interfere
  • Durability: Committed data persists

Using Transactions

const session = await mongoose.startSession();
session.startTransaction();

try {
  await db.accounts.updateOne(
    { _id: "A" },
    { $inc: { balance: -100 } },
    { session }
  );
  
  await db.accounts.updateOne(
    { _id: "B" },
    { $inc: { balance: 100 } },
    { session }
  );
  
  await session.commitTransaction();
} catch (error) {
  await session.abortTransaction();
} finally {
  session.endSession();
}

8. Replication & Sharding

Replica Sets

  • Primary: Receives all writes
  • Secondary: Replicate from primary
  • Arbiter: Voting only, no data
  • Minimum 3 nodes recommended

Read Preferences

primary          // Default, read from primary
primaryPreferred // Primary if available
secondary        // Read from secondary
secondaryPreferred
nearest          // Lowest latency

Sharding

  • Shard Key: Field(s) to distribute data
  • Chunks: Data ranges
  • Balancer: Moves chunks between shards
// Enable sharding on database
sh.enableSharding("mydb")

// Shard collection
sh.shardCollection("mydb.users", { userId: 1 })

9. Performance Optimization

Query Optimization

// Use explain() to analyze
db.users.find({ age: 30 }).explain("executionStats")

// Key metrics to check:
// - totalDocsExamined vs totalDocsReturned
// - executionTimeMillis
// - indexUsed

Query Optimization Best Practices

  1. Create indexes on frequently queried fields
  2. Use projection to limit returned fields
  3. Avoid $where and JavaScript execution
  4. Use covered queries (all fields in index)
  5. Limit results with pagination
  6. Batch operations when possible

10. Security

Authentication & Authorization

// Create user
db.createUser({
  user: "appUser",
  pwd: "password",
  roles: [
    { role: "readWrite", db: "myapp" }
  ]
})

// Built-in roles
read         // Read data
readWrite    // Read and write
dbAdmin      // Database administration
userAdmin    // User administration

Security Best Practices

  1. Enable authentication
  2. Use SSL/TLS for connections
  3. Restrict network access
  4. Regular backups
  5. Audit logs
  6. Field-level encryption for sensitive data

11. Use Cases & Design Patterns

When to Use MongoDB

Good for:

  • Content management systems
  • Real-time analytics and IoT data
  • Product catalogs with varying attributes
  • Social networks and user-generated content
  • Gaming leaderboards and player profiles
  • Session storage and caching

Not ideal for:

  • Complex multi-table transactions
  • Fixed schema requirements
  • Financial systems requiring strict ACID
  • Heavy JOIN operations

MongoDB vs SQL Databases

CAP Theorem Implementation

  • Consistency: Strong consistency with readConcern: "majority"
  • Availability: High availability through replica sets
  • Partition Tolerance: Automatic failover and sharding

Write Concern Levels

Level Description Use Case
w: 0 No acknowledgment Fire-and-forget logging
w: 1 Primary acknowledged Default, most operations
w: "majority" Majority of nodes Critical data
j: true Journaled to disk Maximum durability

Common Query Patterns

Time-Based Queries

// Users active in last 30 days
db.users.find({
  lastLogin: { 
    $gte: new Date(Date.now() - 30*24*60*60*1000) 
  },
  status: "active"
})

// Events in date range
db.events.find({
  date: {
    $gte: ISODate("2024-01-01"),
    $lt: ISODate("2024-02-01")
  }
})

Analytics Queries

// Top products by sales
db.orders.aggregate([
  { $unwind: "$items" },
  { $group: {
      _id: "$items.productId",
      totalRevenue: { $sum: { $multiply: ["$items.price", "$items.quantity"] } },
      totalQuantity: { $sum: "$items.quantity" }
  }},
  { $sort: { totalRevenue: -1 } },
  { $limit: 10 },
  { $lookup: {
      from: "products",
      localField: "_id",
      foreignField: "_id",
      as: "product"
  }}
])

// User engagement metrics
db.activities.aggregate([
  { $match: { 
      timestamp: { $gte: new Date(Date.now() - 7*24*60*60*1000) }
  }},
  { $group: {
      _id: {
        user: "$userId",
        action: "$actionType"
      },
      count: { $sum: 1 }
  }},
  { $group: {
      _id: "$_id.user",
      actions: {
        $push: {
          type: "$_id.action",
          count: "$count"
        }
      },
      totalActions: { $sum: "$count" }
  }}
])

Working with Arrays

// Update nested array element
db.users.updateOne(
  { _id: 1, "addresses.type": "home" },
  { $set: { "addresses.$.city": "Boston" } }
)

// Add to array if not exists
db.users.updateOne(
  { _id: 1 },
  { $addToSet: { tags: "premium" } }
)

// Update all array elements
db.products.updateMany(
  {},
  { $mul: { "variants.$[].price": 1.1 } }  // 10% price increase
)

Advanced Schema Design Patterns

Polymorphic Pattern

// Products with different attributes
{
  _id: ObjectId("..."),
  type: "book",
  title: "MongoDB Guide",
  author: "John Doe",
  isbn: "123-456",
  pages: 300
}
{
  _id: ObjectId("..."),
  type: "electronics",
  name: "Laptop",
  brand: "Dell",
  specs: {
    cpu: "Intel i7",
    ram: "16GB"
  }
}

Bucket Pattern (Time Series)

// Aggregate time-series data into buckets
{
  _id: ObjectId("..."),
  sensorId: "sensor001",
  startTime: ISODate("2024-01-01T00:00:00Z"),
  endTime: ISODate("2024-01-01T01:00:00Z"),
  measurements: [
    { timestamp: ISODate("2024-01-01T00:00:00Z"), temp: 22.5 },
    { timestamp: ISODate("2024-01-01T00:01:00Z"), temp: 22.7 },
    // ... up to 60 measurements
  ],
  metadata: {
    avgTemp: 22.6,
    maxTemp: 23.1,
    minTemp: 22.3
  }
}

Computed Pattern

// Pre-compute expensive calculations
{
  _id: ObjectId("..."),
  productId: "prod123",
  ratings: [5, 4, 5, 3, 4],
  // Pre-computed fields
  avgRating: 4.2,
  totalRatings: 5,
  ratingDistribution: {
    5: 2,
    4: 2,
    3: 1
  }
}

## 12. MongoDB vs SQL Quick Reference

| Operation | SQL | MongoDB |
|-----------|-----|---------|
| Create Table/Collection | CREATE TABLE users | db.createCollection("users") |
| Insert | INSERT INTO users VALUES | db.users.insertOne({}) |
| Select All | SELECT * FROM users | db.users.find() |
| Where | WHERE age > 25 | { age: { $gt: 25 } } |
| Join | JOIN orders ON... | $lookup aggregation |
| Group By | GROUP BY status | $group aggregation |
| Order By | ORDER BY age DESC | .sort({ age: -1 }) |
| Limit | LIMIT 10 | .limit(10) |
| Update | UPDATE users SET... | db.users.updateOne() |
| Delete | DELETE FROM users | db.users.deleteOne() |

## 13. Troubleshooting & Optimization

### Common Performance Issues

#### Slow Queries
```javascript
// Analyze query performance
db.users.find({ age: { $gt: 25 } }).explain("executionStats")

// Key metrics to check:
{
  executionStats: {
    totalDocsExamined: 10000,  // Should be close to totalReturned
    totalDocsReturned: 100,
    executionTimeMillis: 50,
    indexesUsed: ["age_1"]
  }
}

Memory Issues

// Check collection stats
db.users.stats()

// Monitor working set
db.serverStatus().wiredTiger.cache

// Limit memory usage for queries
db.adminCommand({ setParameter: 1, internalQueryExecMaxBlockingSortBytes: 33554432 })

Connection Issues

// Check current connections
db.serverStatus().connections

// Set connection pool size (Node.js example)
const options = {
  maxPoolSize: 100,
  minPoolSize: 10,
  maxIdleTimeMS: 10000
}

Index Optimization

// Find missing indexes
db.users.aggregate([
  { $indexStats: {} },
  { $match: { "accesses.ops": { $lt: 100 } } }
])

// Remove unused indexes
db.users.dropIndex({ field: 1 })

// Create compound index for common queries
db.orders.createIndex({ userId: 1, status: 1, createdAt: -1 })

Monitoring Commands

// Real-time operations
db.currentOp()

// Kill long-running operation
db.killOp(opId)

// Database profiler
db.setProfilingLevel(1, { slowms: 100 })
db.system.profile.find().limit(5).sort({ ts: -1 })

14. Key Takeaways

Architecture & Design

  • Document model provides schema flexibility
  • Horizontal scaling through automatic sharding
  • High availability via replica sets with automatic failover
  • Choose embedding vs referencing based on access patterns

Performance & Operations

  • Indexes are crucial - Monitor and optimize regularly
  • Aggregation framework enables complex analytics
  • Use projections to reduce network overhead
  • Write concerns balance durability vs performance

Modern Features

  • ACID transactions for multi-document operations (v4.0+)
  • Change streams for real-time data pipelines
  • Schema validation for data integrity when needed
  • Time series collections optimized for IoT data (v5.0+)

Best Practices Summary

  1. Design schema based on query patterns
  2. Use appropriate indexes but avoid over-indexing
  3. Implement proper error handling and retries
  4. Monitor performance metrics regularly
  5. Plan sharding strategy early for large datasets
  6. Use connection pooling effectively
  7. Implement proper backup and disaster recovery
Found this useful? Pass it on.
Pro · $10/mo

The sheet is free. Pro goes deeper.

Pro opens the full question library behind every sheet, every refresher and a monthly AI allowance. One subscription, all formats.

Full question library All refreshers Cancel anytime