Python Tutorial
Python MongoDB - Get Started
Connect Python to MongoDB with PyMongo and understand documents, collections, and databases.
What Is MongoDB?
MongoDB is a NoSQL document database. Instead of tables and rows, it stores flexible, JSON-like documents (BSON) grouped into collections. Documents in one collection need not share the same fields, which suits evolving or semi-structured data.
| SQL term | MongoDB term |
|---|---|
| Database | Database |
| Table | Collection |
| Row | Document |
| Column | Field |
Install PyMongo
pip install pymongoPyMongo is the official MongoDB driver for Python. For MongoDB Atlas (cloud), also install pymongo[srv] to support mongodb+srv:// connection strings.
Connect to the Server
from pymongo import MongoClient
client = MongoClient("mongodb://localhost:27017/")
# For Atlas:
# client = MongoClient("mongodb+srv://user:pass@cluster.mongodb.net/")
print(client.list_database_names()) # existing databasesKeep credentials out of source code. Read the connection string from an environment variable such as os.environ["MONGODB_URI"].
Documents Are Python Dicts
A MongoDB document maps directly to a Python dictionary — this is what makes PyMongo feel natural.
customer = {
"name": "John",
"address": "Highway 37",
"tags": ["vip", "newsletter"], # arrays are fine
"profile": {"age": 30}, # nested documents are fine
}Verify the Connection
MongoDB connects lazily, so send a lightweight command to confirm the server is reachable.
from pymongo.errors import ConnectionFailure
try:
client.admin.command("ping")
print("Connected to MongoDB.")
except ConnectionFailure as e:
print("Connection failed:", e)Best Practices
- Create one
MongoClientfor your app and reuse it — it manages a connection pool internally. - Store connection strings in environment variables or a secrets manager.
- Ping the server on startup to fail fast on misconfiguration.
- Next up: creating databases and collections, then inserting and querying documents.
Try It Yourself
Exercise 1: Match the MongoDB term to its SQL equivalent: collection, document, field.
Show solution
collection = table, document = row, field = column.
Exercise 2: Which library and import connect Python to MongoDB?
Show solution
pip install pymongo
from pymongo import MongoClient📘 Real-World Deep Dive
MongoDB stores JSON-shaped documents and queries them with a JSON-shaped filter language. PyMongo's API mirrors the wire protocol — once you know the query language, you know the driver.
Real-Life Scenario
A small product catalog: insert a handful of documents with mixed fields, then query with projection, sort, and limit to build a sorted list of in-stock items.
Real-Life Example
from pymongo import MongoClient, DESCENDING
from datetime import datetime, timezone
c = MongoClient("mongodb://localhost:27017")
db = c.shop
items = db.products
# Wipe-and-seed
items.drop()
items.insert_many([
{"sku": "MUG-1", "name": "Ceramic Mug", "price": 12.5, "stock": 24, "tags": ["kitchen"]},
{"sku": "TS-1", "name": "T-Shirt", "price": 22.0, "stock": 12, "tags": ["apparel"]},
{"sku": "CAP-1", "name": "Cap", "price": 18.0, "stock": 0, "tags": ["apparel"]},
{"sku": "BTL-1", "name": "Water Bottle", "price": 24.0, "stock": 5, "tags": ["kitchen", "eco"]},
])
cursor = (
items.find({"stock": {"$gt": 0}}, projection={"name": 1, "price": 1, "_id": 0})
.sort("price", DESCENDING)
.limit(3)
)
for doc in cursor:
print(doc)Expected Output
{'name': 'Water Bottle', 'price': 24.0}
{'name': 'T-Shirt', 'price': 22.0}
{'name': 'Ceramic Mug', 'price': 12.5}Common mistakes
datetime.now()withouttimezone.utcdrops tz info — Mongo will silently treat it as naive.- Projections on
find()shrink the wire payload; not projecting can be 100× slower. - Indexes aren't auto-created on first query — call
create_indexexplicitly.
🚀 Performance & Best Practices
- Use
bulk_writefor batched inserts/updates — orders of magnitude faster than loops. - Avoid
$wherequeries — they're per-document JS evaluations. - Cache the latest catalog snapshot in your app and refresh every N seconds.
🧪 Try It Yourself
- Add
items.create_index([("stock", 1), ("price", -1)])for the query above. - Build a class wrapper around the driver so tests can inject a mock connection.
- Add
update_manyfor a bulk inventory update.