PyMongo 入门指南:Python 操作 MongoDB

PyMongo 是 MongoDB 官方 Python 驱动。本文讲解 MongoClient 连接池、CRUD、聚合和索引,并说明异步驱动选择及查询诊断。

最佳实践
并发任务的多路径协同插画

直接回答:PyMongo 是 MongoDB 的官方 Python 驱动:连接即池,插入查询都是直观的字典操作,聚合管道、地理索引、事务等高级特性全覆盖——Python 应用对接 MongoDB 的官方驱动选择。

连接 MongoDB

pip install pymongo
from pymongo import MongoClient

client = MongoClient("mongodb://localhost:27017/")
db = client["blog"]           # 数据库
posts = db["posts"]           # 集合(首次写入时自动创建)

# 连通性检查
print(client.admin.command("ping"))

MongoClient 内置连接池与自动重连——通常每个进程复用一个实例,进程退出时关闭;不要把父进程的客户端直接交给 fork 后子进程,反复 new 是性能反模式。

集合与文档的心智模型

集合 ≈ 表,文档 ≈ 行——但文档是灵活的 BSON:字段可不同、可嵌套数组与子文档。Schema 自由是把双刃剑:应用层要做好字段约束(Pydantic 模型是常见搭档)。

插入

post = {
    "title": "MongoDB 入门",
    "author": "张三",
    "tags": ["数据库", "NoSQL"],
    "views": 0,
}

result = posts.insert_one(post)
print(result.inserted_id)     # ObjectId

posts.insert_many([{"title": "文章 A", "views": 0}, {"title": "文章 B", "views": 0}])
pid = result.inserted_id

查询

# 单条
post = posts.find_one({"title": "MongoDB 入门"})

# 条件查询
for p in posts.find({"author": "张三"}).sort("views", -1).limit(10):
    print(p["title"])

# 操作符
posts.find({"views": {"$gt": 100}})                        # 大于
posts.find({"tags": {"$in": ["数据库"]}})                  # 数组包含
posts.find({"title": {"$regex": "Mongo", "$options": "i"}})  # 模糊
posts.find({}, {"title": 1, "author": 1})                  # 投影(只取字段)

游标是惰性的——遍历才真正拉数据,按批次获取可减少峰值内存,但并非零占用。

更新

# 单字段更新
posts.update_one({"_id": pid}, {"$set": {"views": 101}})

# 原子自增(计数器场景必备)
posts.update_one({"_id": pid}, {"$inc": {"views": 1}})

# 数组操作
posts.update_one({"_id": pid}, {"$push": {"tags": "教程"}})

# 批量
posts.update_many({"author": "张三"}, {"$set": {"verified": True}})

# 不存在则插入(upsert)
data = {"title": "Hello", "views": 0}
posts.update_one({"slug": "hello"}, {"$set": data}, upsert=True)

删除

posts.delete_one({"_id": pid})
posts.delete_many({"views": 0})    # 清空零阅读草稿

进阶速览

  • 聚合管道:posts.aggregate([{"$group": {"_id": "$author", "total": {"$sum": "$views"}}}])——数据分析不走应用层循环;
  • 索引:posts.create_index([("title", "text")]),查询慢先查索引;
  • 事务:副本集/集群上 with client.start_session() as s: s.with_transaction(...)。

常见问题(FAQ)

Q:PyMongo 有异步版本吗?
A:有,优先使用 PyMongo 的 AsyncMongoClient;Motor 已弃用,存量用户按官方指南迁移。同步驱动不能直接阻塞异步事件循环,也可通过同步端点或受控线程池运行。

Q:ObjectId 和字符串 ID 怎么选?
A:默认 ObjectId 自带时间戳与分布式唯一性,直接用;需要 URL 友好或外部系统对接时用字符串,但要自己保证唯一。

Q:查询越来越慢怎么排查?
A:PyMongo Cursor.explain() 不接受 mongosh 的字符串参数;需要指定执行统计时使用 db.command("explain", {"find": "posts", "filter": {...}}, verbosity="executionStats"),其中过滤条件需替换成真实字典;再看文档体积(是否该投影瘦身);最后看数据模型(频繁一起查的字段该内嵌而非分列)。

官方参考

本文基于官方文档整理,未进行运行时或性能测试。示例中的业务函数、数据模型和部署地址需结合项目补全;局部片段不等同于完整生产应用。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台