Python连接MongoDB怎么做_PyMongo实现NoSQL增删改查
PyMongo安装应直接用pip install pymongo,连接字符串写mongodb://localhost:27017/并加serverSelectionTimeoutMS=5000;insert_one传单字典、insert_many传非空字典列表且字段名不能含.或$;find返回Cursor需遍历或转list;update_one必须用$set等操作符避免整文档替换。
PyMongo安装和连接字符串怎么写才不报错
直接用 pip install pymongo 装,别装 pymongo[srv] 或带额外后缀的——除非你真用 MongoDB Atlas 的 SRV 记录。本地或普通云数据库,连 mongodb://localhost:27017 就够了。
常见错误是漏掉协议头、端口写错,或者把用户名密码拼在 URL 里时没做 URL 编码。比如密码含 @ 或 /,不编码就会被当成 URL 分隔符,导致解析失败。
连接时加 serverSelectionTimeoutMS=5000 参数,避免网络不通时卡死 30 秒:
from pymongo import MongoClient
client = MongoClient("mongodb://localhost:27017/", serverSelectionTimeoutMS=5000)
try:
client.admin.command('ping') # 真正触发连接检测
except Exception as e:
print(f"连接失败:{e}")
insert_one 和 insert_many 的坑在哪
insert_one 只收单个 dict;insert_many 收 list of dict,但别传空列表——它不会报错,但会静默跳过,容易误以为数据写进去了。
插入前检查字段名是否含点(.)或美元符号($),MongoDB 不允许这些字符出现在 key 里,会直接抛 InvalidDocument 错误。
如果要批量写入上万条,别一股脑传大 list 给 insert_many。内存吃紧不说,万一中途断连,整批重试成本高。建议每 100–500 条分一批:
- 用
bypass_document_validation=True跳过 schema 校验(仅限开发环境) - 加
ordered=False让失败项不影响后续插入(适合容忍部分失败的场景) - 插入后检查返回的
result.inserted_ids长度,确认数量对得上
find 返回的是 cursor,不是 list
这是最常被忽略的一点:collection.find({}) 返回的是 Cursor 对象,不是 Python list。直接 print 它只显示对象地址,不输出数据。
想看内容,得遍历或转成 list:
Nanobot
开源、超轻量级个人AI智能体
cursor = collection.find({"status": "active"})
for doc in cursor: # ✅ 正确:边取边迭代,省内存
print(doc)
或一次性转 list(小数据可用)
docs = list(collection.find({"status": "active"})) # ❌ 大数据慎用,全加载进内存
另外,find 默认不排序、不限制数量。查日志类集合时,忘了加 .sort("_id", -1).limit(10),可能拿到一堆旧数据还觉得“怎么查不到最新那条”。
update_one 为什么改不了字段或没反应
默认情况下,update_one 只更新匹配文档的字段,不会删掉其他字段。但如果你传的是完整 dict,又没写 $set 操作符,MongoDB 会把它当「替换整个文档」——旧字段全丢。
正确写法必须显式用更新操作符:
# ❌ 这样是替换整个文档(危险!)
collection.update_one({"_id": id}, {"name": "new", "age": 25})
✅ 这样才是局部更新
collection.update_one({"_id": id}, {"$set": {"name": "new", "age": 25}})
还有两个易错点:
-
upsert=True时,如果匹配不到,会插入一个只有 filter 字段的新文档(不是你传的 update 内容),除非你同时用$setOnInsert - 更新时间字段如
updated_at,别依赖 Python 的datetime.now()在应用层生成——时区不一致、服务多实例时可能出错,建议用$currentDate操作符
MongoDB 的原子性只在单文档内有效,跨文档逻辑(比如“扣库存 + 写订单”)得靠应用层控制。别指望靠一个 update 语句搞定所有业务约束。