Skip to main content

MongoDB

MongoDB

MongoDB is a popular NoSQL document database designed for scalability and developer agility, storing data in flexible JSON-like documents.

Overview

  • Versions: 8.0, 7.0, 6.0
  • Cluster Support: ✅ Yes (Replica sets and sharding)
  • Use Cases: Document databases, JSON storage, real-time analytics
  • Features: Auto-backups, replica sets, sharding, aggregation framework

Key Features

  • Document-Oriented: Store data as flexible JSON-like documents (BSON)
  • Schema Flexibility: No rigid schema required, adapt as your app evolves
  • Horizontal Scaling: Built-in sharding for distributing data across nodes
  • High Availability: Replica sets with automatic failover
  • Rich Query Language: Powerful queries, aggregation framework, and indexes
  • ACID Transactions: Multi-document ACID transactions (MongoDB 4.0+)
  • GridFS: Store and retrieve large files
  • Change Streams: Real-time data change notifications

Deployment Modes

MongoDB supports both single-node and cluster deployments:

Single Node

  • Best for development and testing
  • Lower cost, simpler setup
  • Single point of failure
  • Suitable for non-critical workloads

Cluster (Replica Set)

  • Recommended for production workloads
  • High availability with automatic failover
  • 3-10 data nodes configurable
  • Optional arbiter node for tie-breaking
  • Read scaling with secondary reads
  • Zero-downtime maintenance

Resource Tiers

TierCPUMemoryDiskReplicasBest For
Small0.51GB10GB1Development, testing
Medium12GB25GB1Small production apps
Large24GB50GB3 (HA)Production workloads
XLarge48GB100GB3 (HA)High-traffic applications

Creating a MongoDB Add-on

  1. Navigate to Add-onsCreate Add-on
  2. Select MongoDB as the type
  3. Choose a version (8.0, 7.0, or 6.0)
  4. Select deployment mode:
    • Single Node: For development/testing
    • Cluster: For production (3-10 nodes + optional arbiter)
  5. Configure:
    • Label: Descriptive name (e.g., "User Data Store")
    • Description: Purpose and notes
    • Environment: Development or Production
    • Resource Tier: Based on your workload requirements
  6. Configure backups:
    • Schedule: Daily recommended for production
    • Retention: 7+ days for production
  7. Click Create Add-on

Connection Information

After deployment, connection details are available in the add-on details page and automatically injected into your apps via STRONGLY_SERVICES.

Connection String Format

Single Node:

mongodb://username:password@host:27017/database

Replica Set:

mongodb://username:password@host1:27017,host2:27017,host3:27017/database?replicaSet=rs0

Accessing Connection Details

import os
import json
from pymongo import MongoClient

# Parse STRONGLY_SERVICES
services = json.loads(os.environ.get('STRONGLY_SERVICES', '{}'))

# Get MongoDB add-on connection
mongodb_addon = services['addons']['addon-id']

# Connect using connection string
client = MongoClient(mongodb_addon['connectionString'])
db = client[mongodb_addon['database']]

# Or connect using individual parameters
client = MongoClient(
host=mongodb_addon['host'],
port=mongodb_addon['port'],
username=mongodb_addon['username'],
password=mongodb_addon['password']
)
db = client[mongodb_addon['database']]

# Query documents
users = db.users.find({'active': True})
for user in users:
print(user)

Common Operations

Creating Collections and Documents

// Collections are created automatically when you insert documents
db.users.insertOne({
email: 'user@example.com',
username: 'johndoe',
active: true,
profile: {
firstName: 'John',
lastName: 'Doe',
age: 30
},
tags: ['premium', 'verified'],
createdAt: new Date()
});

// Insert multiple documents
db.users.insertMany([
{ email: 'alice@example.com', username: 'alice', active: true },
{ email: 'bob@example.com', username: 'bob', active: false }
]);

Querying Documents

// Find all active users
db.users.find({ active: true });

// Find with nested field
db.users.find({ 'profile.age': { $gte: 25 } });

// Find with array contains
db.users.find({ tags: 'premium' });

// Find with multiple conditions
db.users.find({
active: true,
'profile.age': { $gte: 18, $lte: 65 }
});

// Projection (select specific fields)
db.users.find(
{ active: true },
{ email: 1, username: 1, _id: 0 }
);

// Sort and limit
db.users.find({ active: true })
.sort({ createdAt: -1 })
.limit(10);

Updating Documents

// Update one document
db.users.updateOne(
{ email: 'user@example.com' },
{
$set: { active: false },
$currentDate: { lastModified: true }
}
);

// Update multiple documents
db.users.updateMany(
{ 'profile.age': { $lt: 18 } },
{ $set: { 'profile.minor': true } }
);

// Update with operators
db.users.updateOne(
{ email: 'user@example.com' },
{
$inc: { 'stats.loginCount': 1 },
$push: { tags: 'new-tag' },
$set: { lastLogin: new Date() }
}
);

// Upsert (update or insert)
db.users.updateOne(
{ email: 'newuser@example.com' },
{ $set: { username: 'newuser', active: true } },
{ upsert: true }
);

Deleting Documents

// Delete one document
db.users.deleteOne({ email: 'user@example.com' });

// Delete multiple documents
db.users.deleteMany({ active: false });

// Delete all documents in collection
db.users.deleteMany({});

Indexing

Indexes improve query performance significantly.

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

// Create compound index
db.users.createIndex({ username: 1, active: 1 });

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

// Create text index for full-text search
db.articles.createIndex({ title: 'text', content: 'text' });

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

// Create partial index (index subset of documents)
db.users.createIndex(
{ email: 1 },
{ partialFilterExpression: { active: true } }
);

// List all indexes
db.users.getIndexes();

// Drop index
db.users.dropIndex('email_1');

Aggregation Framework

Powerful data processing and analysis pipeline.

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

// Complex aggregation with lookup (join)
db.orders.aggregate([
{
$lookup: {
from: 'users',
localField: 'userId',
foreignField: '_id',
as: 'user'
}
},
{ $unwind: '$user' },
{
$project: {
orderDate: 1,
amount: 1,
userName: '$user.username',
userEmail: '$user.email'
}
}
]);

// Aggregation with date operations
db.events.aggregate([
{
$group: {
_id: {
year: { $year: '$timestamp' },
month: { $month: '$timestamp' }
},
count: { $sum: 1 }
}
}
]);

Transactions

Multi-document ACID transactions for data consistency.

from pymongo import MongoClient

client = MongoClient(connection_string)
db = client.database

# Start a session
with client.start_session() as session:
# Start a transaction
with session.start_transaction():
try:
# Multiple operations in transaction
db.accounts.update_one(
{'accountId': 'A'},
{'$inc': {'balance': -100}},
session=session
)
db.accounts.update_one(
{'accountId': 'B'},
{'$inc': {'balance': 100}},
session=session
)
# Transaction commits automatically if no exception
except Exception as e:
# Transaction aborts on exception
print(f"Transaction aborted: {e}")
raise

Backup & Restore

MongoDB add-ons use mongodump for backups, creating complete BSON dumps of your database.

Backup Configuration

  • Tool: mongodump
  • Format: .archive
  • Includes: Full database dump with indexes
  • Storage: AWS S3 (s3://strongly-backups/backups/<addon-id>/)

Manual Backup

  1. Go to add-on details page
  2. Click Backup Now
  3. Monitor progress in job logs
  4. Backup saved as backup-YYYYMMDDHHMMSS.archive

Scheduled Backups

Configure during add-on creation or in settings:

  • Daily backups: Recommended for production
  • Retention: 7-14 days minimum for production
  • Custom cron: For specific schedules (e.g., 0 2 * * * for 2 AM daily)

Restore Process

  1. Navigate to Backups tab
  2. Select backup from list
  3. Click Restore
  4. Confirm (add-on will stop temporarily)
  5. Data restored using mongorestore
  6. Add-on automatically restarts
Data Loss

Restoring from backup replaces ALL current data. Create a current backup first if needed.

Performance Optimization

Connection Pooling

from pymongo import MongoClient

# Connection pooling is automatic, configure pool size
client = MongoClient(
connection_string,
maxPoolSize=50,
minPoolSize=10
)

Query Optimization

// Use explain() to analyze queries
db.users.find({ email: 'user@example.com' }).explain('executionStats');

// Check if index is used
db.users.find({ active: true }).explain('executionStats').executionStats.totalDocsExamined;

// Use projection to reduce data transfer
db.users.find(
{ active: true },
{ email: 1, username: 1 } // Only return these fields
);

// Use covered queries (query satisfied by index alone)
db.users.createIndex({ email: 1, username: 1 });
db.users.find(
{ email: 'user@example.com' },
{ email: 1, username: 1, _id: 0 }
);

Schema Design Best Practices

  1. Embed vs Reference: Embed frequently accessed related data, reference rarely accessed data
  2. Avoid Unbounded Arrays: Use references or bucketing for growing arrays
  3. Optimize for Read Patterns: Design schema based on how you query data
  4. Use Appropriate Data Types: Use proper types (Date, ObjectId, etc.)
// Good: Embedded document for 1-to-few
{
_id: ObjectId('...'),
username: 'johndoe',
addresses: [
{ street: '123 Main St', city: 'NYC', type: 'home' },
{ street: '456 Work Ave', city: 'NYC', type: 'work' }
]
}

// Good: Reference for 1-to-many
{
_id: ObjectId('...'),
username: 'johndoe',
orderIds: [ObjectId('...'), ObjectId('...')]
}

Monitoring

Monitor your MongoDB add-on through the Strongly platform:

  • CPU Usage: Track CPU utilization
  • Memory Usage: Monitor memory consumption
  • Disk Space: Watch disk utilization
  • Connection Count: Active connections
  • Operation Performance: Query execution times
  • Replica Set Status: Health of cluster nodes (if using cluster mode)

Database Statistics

// Database statistics
db.stats();

// Collection statistics
db.users.stats();

// Server status
db.serverStatus();

// Current operations
db.currentOp();

// Connection statistics
db.serverStatus().connections;

Best Practices

  1. Use Indexes: Index fields used in queries, but avoid over-indexing
  2. Enable Connection Pooling: Reuse connections for better performance
  3. Use Projection: Request only needed fields to reduce network traffic
  4. Backup Regularly: Enable daily backups for production databases
  5. Monitor Performance: Use explain() to analyze slow queries
  6. Schema Design: Design schema for your read/write patterns
  7. Use Transactions Sparingly: Only when ACID guarantees are needed
  8. Avoid Large Documents: Keep documents under 16MB limit
  9. Use Replica Sets: Always use replica sets for production
  10. Test Restores: Periodically verify backup restoration
  11. Separate Dev/Prod: Never connect production apps to development databases
  12. Use Appropriate Write Concerns: Balance between performance and durability

Replica Set Configuration

When using cluster mode, MongoDB automatically configures replica sets:

// Check replica set status
rs.status();

// View replica set configuration
rs.conf();

// Check which node is primary
db.isMaster();

Read Preferences

from pymongo import MongoClient, ReadPreference

# Read from primary only (default, strongest consistency)
client = MongoClient(connection_string)

# Read from secondary when possible (eventual consistency)
client = MongoClient(
connection_string,
readPreference=ReadPreference.SECONDARY_PREFERRED
)

# Read from nearest node (lowest latency)
client = MongoClient(
connection_string,
readPreference=ReadPreference.NEAREST
)

Migration Guide

From Relational Database to MongoDB

Key concepts mapping:

RelationalMongoDB
DatabaseDatabase
TableCollection
RowDocument
ColumnField
IndexIndex
JOINEmbedded docs or $lookup
Foreign KeyReference

Example transformation:

-- SQL
SELECT users.username, orders.amount
FROM users
JOIN orders ON users.id = orders.user_id
WHERE users.active = true;
// MongoDB with embedded documents
db.users.find(
{ active: true },
{ username: 1, 'orders.amount': 1 }
);

// MongoDB with $lookup (join)
db.users.aggregate([
{ $match: { active: true } },
{
$lookup: {
from: 'orders',
localField: '_id',
foreignField: 'userId',
as: 'orders'
}
},
{
$project: {
username: 1,
'orders.amount': 1
}
}
]);

Troubleshooting

Connection Issues

// Test connection
const { MongoClient } = require('mongodb');
const client = new MongoClient(connectionString);

await client.connect();
console.log('Connected successfully');
await client.close();

Performance Issues

// Find slow queries
db.system.profile.find({ millis: { $gt: 1000 } }).sort({ ts: -1 }).limit(10);

// Enable profiling to track slow queries
db.setProfilingLevel(1, { slowms: 100 });

// Check current operations
db.currentOp({ 'active': true, 'secs_running': { $gt: 5 } });

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

Disk Space Issues

// Check database size
db.stats(1024*1024); // Size in MB

// Check collection sizes
db.getCollectionNames().forEach(function(collection) {
var stats = db.getCollection(collection).stats(1024*1024);
print(collection + ': ' + stats.size + ' MB');
});

// Compact collection to reclaim space
db.runCommand({ compact: 'users' });

Support

For issues or questions:

  • Check add-on logs in the Strongly dashboard
  • Review MongoDB official documentation
  • Contact Strongly support through the platform