mongodb导出csv需先将cursor转为列表并预处理:用list(collection.find())生成dataframe,转objectid为str,展平嵌套字段,剔除无关列,导出时指定encoding="utf-8-sig"防乱码。

直接用 pandas.DataFrame.to_csv() 导出 MongoDB 数据是可行的,但必须先正确加载数据——关键不在“怎么导出”,而在“怎么把 cursor 变成能被 pandas 处理的结构”,否则会报 TypeError: 'Cursor' object is not iterable 或空 CSV。
用 list(cursor) 把 MongoDB 查询结果转成 Python 列表
MongoDB 的 collection.find() 返回的是惰性游标(Cursor),pandas 无法直接读取。不能直接传给 pd.DataFrame(),必须先取值。
- ✅ 正确做法:
data = list(collection.find({})),再传给pd.DataFrame(data) - ❌ 错误写法:
pd.DataFrame(collection.find({}))—— 这会触发TypeError - ⚠️ 注意:如果数据量大(比如 >10 万条),
list()会一次性加载全部到内存,可能 OOM;此时应分批用cursor.batch_size()+ 循环写入 CSV,不经过 pandas
处理 ObjectId 和嵌套字段导致 CSV 写入失败
默认情况下,MongoDB 的 _id: ObjectId("...") 和深层嵌套字典(如 {"user": {"name": "A", "tags": ["x"]}})会让 to_csv() 报错或生成不可读字段。
- 必须预处理:
df["_id"] = df["_id"].astype(str),否则 CSV 中该列为空或报TypeError: Object of type ObjectId is not JSON serializable - 嵌套字段不会自动展平——
pandas默认保留为字符串(如"{'name': 'A'}"),若需展开,得用pd.json_normalize() - 示例展平:
df = pd.json_normalize(list(collection.find({})), sep="_"),这样{"addr": {"city": "BJ"}}就变成列addr_city
导出时忽略 MongoDB 元字段或控制字段顺序
CSV 字段顺序混乱、多出不需要的字段(如 _id、__v)很常见,to_csv() 本身不筛选字段,得靠 DataFrame 预处理。
- 排除特定字段:
df.drop(columns=["_id", "__v"], errors="ignore") - 只保留指定字段并排序:
df[["name", "email", "created_at"]](字段名不存在会报KeyError,加errors="ignore"可跳过) - 注意:MongoDB 文档结构可能不统一(某些文档有
phone,某些没有),pd.DataFrame()会自动补NaN,导出 CSV 后就是空单元格,属正常行为
中文字段名和内容乱码问题(Windows 最常踩坑)
在 Windows 上用 Excel 打开 CSV 中文乱码,几乎全是编码没设对,跟 pandas 无关,而是 to_csv() 的 encoding 参数没配好。
- ✅ 导出时强制用 UTF-8 with BOM:
df.to_csv("out.csv", encoding="utf-8-sig", index=False) - ❌ 不要用
encoding="utf-8"(Excel 打不开中文)、也别用"gbk"(跨平台易出错) - 额外提醒:
index=False必须加,否则第一列是行号,不是原始数据
真正卡住人的往往不是语法,而是游标没转列表、ObjectId 没转字符串、或者 Windows 下忘了 utf-8-sig——这三处一漏,CSV 就要么空,要么乱码,要么打不开。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











