Course topics

By WebNest Studio

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

Python
# 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"}))
Output
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

Python
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()))
Output
matched: 1 modified: 1
discounted: 2
upserted new id: True
deleted: 2
['Headphones', 'Mouse', 'Stapler']

Indexes and the aggregation pipeline

Python
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)
Output
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.