pip install pymongo # or "pymongo[srv]" for Atlas★Thesrvextra enablesmongodb+srv://connection strings used by MongoDB Atlas.from pymongo import MongoClient client = MongoClient("mongodb://localhost:27017/")★One client per app — it's a connection pool, thread-safe, and connects lazily on first operation. Atlas:MongoClient("mongodb+srv://user:pass@cluster.mongodb.net/").client.admin.command("ping") # verify connectivitySince connection is lazy, ping to fail fast at startup if the server is unreachable.client.close() # at shutdown; don't create one per requestReuse the single client for the process lifetime. Creating clients per request exhausts connections.
db = client["shop"] # or client.shop users = db["users"] # a collection★Databases and collections are created lazily on first write — noCREATEneeded.res = users.insert_one({"name": "Ada", "age": 36}) res.inserted_id # ObjectId(...)★Documents are plain dicts. If you omit_id, MongoDB assigns an ObjectId. Nested dicts/lists are fine.res = users.insert_many([{"name": "Al"}, {"name": "Grace"}]) res.inserted_ids★Batch insert.ordered=Falsekeeps going past a failing doc (e.g. duplicate key).from bson import ObjectId users.find_one({"_id": ObjectId("665f1c...")})_idis an ObjectId, not a string — wrap a hex id from a URL/param inObjectId()to query by it.
users.find_one({"name": "Ada"}) # one dict or None★Exact match on a field. An empty filter{}matches everything.for doc in users.find({"age": {"$gt": 30}}): ... # find() returns a lazy cursor★Operators:$gt $gte $lt $lte $ne $in $nin $and $or $exists $regex. The cursor streams — iterate once.users.find({}, {"name": 1, "_id": 0}) \ .sort("age", -1).limit(10).skip(20)★Projection (2nd arg):1include /0exclude. Chainsort/limit/skipon the cursor.users.count_documents({"age": {"$gte": 18}})Exact count for a filter.estimated_document_count()is fast but approximate (whole collection only).