导出MongoDB集合为JSON需先将find()游标转为列表并处理ObjectId和datetime,大数据量须流式分批写入,多集合导出应动态获取名称并清洗文件名,mongoexport更稳定但定制性差。

导出单个集合时,用 find() 配合 json.dumps() 最直接
MongoDB 的 find() 返回的是游标(cursor),不能直接 JSON 序列化,常见错误是直接传给 json.dumps() 导致 TypeError: Object of type Cursor is not JSON serializable。
正确做法是先转成列表,再处理 ObjectId 和日期等非标准类型:
import json
from bson import ObjectId
from datetime import datetime
from pymongo import MongoClient
<p>def json_serializer(obj):
if isinstance(obj, ObjectId):
return str(obj)
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError(f"Object of type {type(obj)} is not JSON serializable")</p><p>client = MongoClient("mongodb://localhost:27017/")
db = client["mydb"]
collection = db["users"]</p><p>data = list(collection.find({})) # 必须转 list,否则无法序列化
with open("users.json", "w", encoding="utf-8") as f:
json.dump(data, f, default=json_serializer, indent=2)-
list(collection.find({}))是关键一步,漏掉会报错 -
default=json_serializer必须提供,否则遇到ObjectId或datetime就崩 - 如果数据量大(比如 >10 万条),
list()会一次性加载进内存,可能 OOM
大数据量导出必须用游标分批 + yield 流式写入
当集合有几十万或上百万文档时,全量 list() 很危险。要用 batch_size 控制每次取多少,并逐批写入文件,避免内存爆炸。
注意:JSON 标准不支持“流式 JSON 数组”,所以得手动拼接格式(开头加 [,每批加逗号分隔,结尾加 ]):
立即学习“Python免费学习笔记(深入)”;
def export_collection_streamed(collection, filename, batch_size=1000):
with open(filename, "w", encoding="utf-8") as f:
f.write("[\n")
first = True
for doc in collection.find().batch_size(batch_size):
if not first:
f.write(",\n")
else:
first = False
json_str = json.dumps(doc, default=json_serializer, indent=2)
f.write(json_str)
f.write("\n]\n")
<p>export_collection_streamed(db["logs"], "logs.json")-
batch_size不是越大越好,通常 1000–5000 较稳妥;设太大仍可能内存压力高 - 必须手动管理 JSON 数组的方括号和逗号,
json.dump()本身不支持追加模式 - 如果中途失败,生成的 JSON 文件会损坏,建议加临时文件 + 原子重命名
导出多个集合时,别硬编码循环,用 list_collection_names() 动态获取
手动写 db.coll1、db.coll2 容易漏、难维护。直接用 db.list_collection_names() 获取所有集合名,再过滤掉系统集合(如 system.indexes)更可靠。
还要注意:某些集合可能为空,find() 返回空游标,list() 得到空列表,json.dump([]) 没问题,但流式写法要单独处理空集合场景。
- 推荐过滤掉以
system.开头的集合:[c for c in db.list_collection_names() if not c.startswith("system.")] - 每个集合单独存一个 JSON 文件,文件名用集合名,避免混在一起难定位
- 如果集合名含特殊字符(如
.、$),文件系统可能不支持,需清洗:re.sub(r"[^a-zA-Z0-9_-]", "_", name)
mongoexport 命令行工具比 Python 脚本更稳,但定制性差
官方 mongoexport 是 C++ 写的,内存友好、支持查询过滤、字段选择、CSV/JSON 双格式,且自动处理 ObjectId 和时间格式(默认转为字符串)。
例如导出带条件的数据:
mongoexport --uri="mongodb://localhost:27017/mydb" \
--collection=orders \
--query='{"status": "completed", "created_at": {"$gte": {"$date": "2024-01-01T00:00:00Z"}}}' \
--out=completed_orders.json- Python 脚本适合需要后处理(比如脱敏、字段映射、合并逻辑)的场景
-
mongoexport不支持嵌套字段重命名或复杂计算,这时才值得写 Python - 注意
--query参数必须是合法 JSON 字符串,单引号包裹,内部双引号要转义
真正麻烦的不是怎么导,而是导出来的 JSON 里 ObjectId 和 Date 已经变成字符串了——如果你后续要用这些字段做查询或校验,得在消费端还原,这点容易被忽略。


















