Python Tutorial
MongoDB with PyMongo
Not every database uses tables. MongoDB is a popular document database: it stores JSON-like documents in collections, and documents in the same collection can have different fields. This suits data with a flexible or nested shape — product catalogues, user profiles, event logs.
Python talks to MongoDB with the official PyMongo driver, and documents are simply Python dictionaries. This lesson covers connecting, inserting, querying with filters and projections, updating, deleting, indexes and the aggregation pipeline.
These examples need a MongoDB server (for example docker run -p 27017:27017 mongo:8) and pip install pymongo, so run them on your own computer.
Documents, Collections and Queries
A document is a dict; every document gets a unique _id (an ObjectId) unless you supply one. A collection groups documents, and a database groups collections — both are created automatically on first insert. Queries are dicts too: {"price": {"$gt": 100}} means price > 100. Common operators are $eq, $ne, $gt, $gte, $lt, $lte, $in, $and, $or and $regex. A projection such as {"_id": 0, "name": 1} chooses which fields to return.
Updates, Indexes and Aggregation
Updates use operators: $set changes fields, $inc adds to numbers, $push appends to arrays, $unset removes fields. upsert=True inserts when nothing matches. Indexes (create_index) make queries fast and can enforce uniqueness. The aggregation pipeline is a list of stages — $match, $group, $sort, $project, $lookup — similar to SQL's WHERE, GROUP BY, ORDER BY and JOIN.
Examples
Connect, insert and query documents
# pip install pymongo
from pymongo import MongoClient, DESCENDING
client = MongoClient("mongodb://localhost:27017/")
db = client["shop"]
products = db["products"]
products.delete_many({}) # start fresh for the demo
result = products.insert_one({"name": "Pen", "price": 20, "tags": ["stationery"]})
print("inserted id type:", type(result.inserted_id).__name__)
products.insert_many([
{"name": "Headphones", "price": 1499, "tags": ["electronics", "audio"]},
{"name": "Mouse", "price": 699, "tags": ["electronics"], "wireless": True},
{"name": "Notebook", "price": 60, "tags": ["stationery"]},
])
print(products.find_one({"name": "Mouse"}, {"_id": 0}))
for doc in products.find({"price": {"$gt": 100}}, {"_id": 0, "name": 1, "price": 1}).sort("price", DESCENDING):
print(doc)
print("electronics:", products.count_documents({"tags": "electronics"}))
inserted id type: ObjectId
{'name': 'Mouse', 'price': 699, 'tags': ['electronics'], 'wireless': True}
{'name': 'Headphones', 'price': 1499}
{'name': 'Mouse', 'price': 699}
electronics: 2
Update, upsert and delete
from pymongo import MongoClient
products = MongoClient("mongodb://localhost:27017/")["shop"]["products"]
res = products.update_one({"name": "Pen"}, {"$set": {"price": 25}, "$push": {"tags": "sale"}})
print("matched:", res.matched_count, "modified:", res.modified_count)
res = products.update_many({"tags": "electronics"}, {"$inc": {"price": -100}})
print("discounted:", res.modified_count)
res = products.update_one({"name": "Stapler"}, {"$set": {"price": 120}}, upsert=True)
print("upserted new id:", res.upserted_id is not None)
res = products.delete_many({"price": {"$lt": 70}})
print("deleted:", res.deleted_count)
print(sorted(p["name"] for p in products.find()))
matched: 1 modified: 1
discounted: 2
upserted new id: True
deleted: 2
['Headphones', 'Mouse', 'Stapler']
Indexes and the aggregation pipeline
from pymongo import MongoClient, ASCENDING
from pymongo.errors import DuplicateKeyError
db = MongoClient("mongodb://localhost:27017/")["shop"]
orders = db["orders"]
orders.drop()
orders.create_index([("order_no", ASCENDING)], unique=True)
orders.insert_many([
{"order_no": 1, "city": "Pune", "total": 1200},
{"order_no": 2, "city": "Mumbai", "total": 800},
{"order_no": 3, "city": "Pune", "total": 450},
{"order_no": 4, "city": "Mumbai", "total": 2300},
])
try:
orders.insert_one({"order_no": 1, "city": "Delhi", "total": 99})
except DuplicateKeyError:
print("order_no 1 already exists")
pipeline = [
{"$match": {"total": {"$gte": 500}}},
{"$group": {"_id": "$city", "orders": {"$sum": 1}, "revenue": {"$sum": "$total"}}},
{"$sort": {"revenue": -1}},
]
for row in orders.aggregate(pipeline):
print(row)
order_no 1 already exists
{'_id': 'Mumbai', 'orders': 2, 'revenue': 3100}
{'_id': 'Pune', 'orders': 1, 'revenue': 1200}
Common Mistakes
- Expecting schema enforcement by default — MongoDB accepts documents with typos in field names unless you add validation.
- Forgetting $set in an update and accidentally trying to replace the whole document.
- Querying large collections on fields without an index.
- Printing ObjectId values and comparing them with strings — convert with str() or ObjectId().
- Building queries from raw user input objects, which allows operator injection (e.g. {"$ne": null}).
Key Points to Remember
- MongoDB stores documents (dicts) in collections; PyMongo is the official driver.
- insert_one/insert_many, find/find_one, update_one/update_many, delete_one/delete_many.
- Queries and updates are dicts with operators such as $gt, $in, $set, $inc and $push.
- Indexes speed up queries and can enforce uniqueness.
- The aggregation pipeline ($match, $group, $sort, $lookup) handles reporting and joins.
Practice the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
Use your local project environment for these examples. Codelab currently runs Python and HTML/CSS/JavaScript; framework examples may need project dependencies.