Python Tutorial
Python MongoDB - Query
Filter documents with MongoDB's query operators: comparisons, logic, arrays, and regex.
Query Documents Are Filters
A query is itself a document. {"name": "John"} means "where name equals John". Operators, written as $-prefixed keys, express richer conditions.
from pymongo import MongoClient
client = MongoClient("mongodb://localhost:27017/")
products = client["shop"]["products"]
products.find({"category": "books"}) # exact matchComparison Operators
| Operator | Meaning |
|---|---|
| $gt / $gte | greater than / or equal |
| $lt / $lte | less than / or equal |
| $ne | not equal |
| $in / $nin | in / not in a list |
products.find({"price": {"$gt": 20}}) # price > 20
products.find({"price": {"$gte": 10, "$lte": 50}}) # 10 <= price <= 50
products.find({"category": {"$in": ["books", "toys"]}})Logical Operators
Multiple keys in one filter are implicitly AND-ed. Use $or, $and, $not for explicit logic.
# implicit AND: in stock AND cheap
products.find({"in_stock": True, "price": {"$lt": 30}})
# explicit OR
products.find({"$or": [{"category": "books"}, {"price": {"$lt": 5}}]})Querying Arrays and Nested Fields
Match array membership directly, or use dot notation to reach into nested documents.
# documents whose tags array contains "sale"
products.find({"tags": "sale"})
# all listed tags must be present
products.find({"tags": {"$all": ["sale", "new"]}})
# nested field with dot notation
client["mydatabase"]["customers"].find({"profile.age": {"$gte": 18}})Regex and Field Existence
import re
# names starting with 'A' (case-insensitive)
products.find({"name": {"$regex": "^A", "$options": "i"}})
products.find({"name": re.compile("^A", re.IGNORECASE)}) # equivalent
# documents that HAVE a discount field
products.find({"discount": {"$exists": True}})Anchored regexes (^A) can use an index; unanchored patterns scan the whole collection. Prefer prefix matches for speed.
Best Practices
- Combine operators to express precise filters instead of fetching and filtering in Python.
- Index fields used in queries — especially range and equality filters.
- Prefer anchored regexes; avoid leading-wildcard patterns on large collections.
- Use the aggregation pipeline for grouping and computed queries beyond simple
find.
Try It Yourself
Exercise 1: Find all products with price greater than 20.
Show solution
products.find({"price": {"$gt": 20}})Exercise 2: Find documents where the tags array contains "sale".
Show solution
products.find({"tags": "sale"})📘 Real-World Deep Dive
Knowing <strong>MongoDB Query (MongoDB)</strong> well is what turns MongoDB from a curiosity into a daily tool — you'll reach for it in nearly every real project.
Real-Life Scenario
An end-to-end usage of MongoDB Query that you'd actually see in a data pipeline or analytics notebook.
Real-Life Example
from pymongo import MongoClient
db = MongoClient().shop
qs = db.orders.find({"total": {"$gte": 50}, "status": {"$in": ["paid", "shipped"]}})
print(sum(1 for _ in qs))Expected Output
(see source)Common mistakes
- Inserting a
dictwith embeddeddatetimeworks, but naivedatetime(without UTC) leads to subtle comparison bugs. - Queries with type-mismatched values silently return no results — cast at the boundary or use
bsoncodecs. find()returns a cursor — calllist(cursor)only once you intend to materialise results.- Treating MongoDB Query as a black box without reading the docs — the API has subtle defaults that bite when you scale.
🚀 Performance & Best Practices
- Project only the fields you need:
collection.find({}, {"name": 1}). - Use
bulk_writeinstead of looping over single inserts / updates — order-of-magnitude faster. - Create indexes:
collection.create_index([("field", pymongo.ASCENDING)]). - When working with MongoDB, prefer vectorised / batched operations over Python loops.
🧪 Try It Yourself
- Reproduce the snippet on a representative slice of your own data.
- Profile the snippet with
cProfileortimeitand find the single biggest improvement. - Generalise the snippet into a small, reusable function you can drop into future projects.