必须先清理Nan/None等非法值,建立唯一索引,然后用upsert插入;在非结构化字段中建立稀疏索引;生产环境需要与schema合作 validator控制字段语义漂移。插入前必须先处理 NaN 和 None 值
混合在爬虫数据中 NaN、None、空字符串甚至嵌套 float('nan'),直接丢给 collection.insert_many() 会报 InvalidDocument: Cannot encode object。MongoDB 的 BSON 标准不支持这些值,PyMongo 也不会自动转换。
实操建议:
立即学习“Python免费学习笔记(深入);
- 用
pandas.isna()或math.isnan()检测浮点型 NaN,统一转为None(BSON 允许null) - 递归清洗字典字段:遇到
None或NaN删除键,或替换占位符"MISSING"(视业务而定) - 避免用
df.fillna("N/A")一刀切-字符串字段填充"N/A"可能会干扰后续工作 NLP 分析 - 插入前加一层校验:
if not isinstance(v, (str, int, float, bool, dict, list, type(None))):过滤掉datetime、Decimal等非原生类型(需要手动转移)
upsert=True 避免重复插入和脏数据
爬虫经常重跑或分片抓取,同样 URL 或 ID 可多次入库。不需要 upsert,依靠应用层重复缓慢和不可靠;硬删再插,破坏原子写入。
实操建议:
立即学习“Python免费学习笔记(深入);
- 唯一的索引定义:
collection.create_index("url", unique=True)或复合索引collection.create_index([("source", 1), ("item_id", 1)], unique=True) - 用
collection.update_one({"url": item["url"]}, {"$set": item}, upsert=True)替代insert_one - 注意:如果
item含_id字段且是 ObjectId 类型,upsert会按_id匹配;否则仅根据查询条件匹配; - 不要在循环中反复调整
create_index()—— 可以在脚本开头或部署时执行一次
非结构化数据字段名不固定,如一些商品 "specifications",有的只有 "attrs",还有空列表或缺失的字段值。普通索引将存储缺失的字段 null,浪费空间,拖慢查询。
Python 3.14.2
Python 3.14.2是Python编程语言于2025年12月5日发布的稳定版本,属于3.14系列的第二次维护更新。该版本包含18个修复项目,重点解决多过程、数据和正则表达模块的回归问题,修复CVE-2025-12084等安全漏洞。这个版本标志着Python发展的一个重要里程碑,即自由线程模式(删除GIL)正式得到官方支持。
下载实操建议:
立即学习“Python免费学习笔记(深入);
- 对于高频查询但可能缺失的字段构建稀疏索引:
collection.create_index("price", sparse=True) - 点号语法用于嵌套字段:
collection.create_index("product.specifications.weight", sparse=True) - 避免对整个子文档进行索引(例如)
"product"),“索引爆炸”很容易触发-每个子键都是单独索引的 - 用
explain("executionStats")验证查询是否真的离开索引,特别注意nReturned和totalDocsExamined是否接近
bypass_document_validation=True 的风险
关闭开发阶段 schema 验证可以加快插入速度,但如果上线后没有配备, validator,脏数据会直接污染收集,后期清洗成本极高。
实操建议:
立即学习“Python免费学习笔记(深入);
- 仅在当地调试或引入历史快照时临时使用:
collection.insert_many(docs, bypass_document_validation=True) - 必须配合生产环境
collMod设置 validator,例如限制price必须是正数:{"$jsonSchema": {"properties": {"price": {"type": "number", "minimum": 0}}}} -
bypass_document_validation不跳过 _id 冲突检查不绕过唯一的索引约束 - 如果用了 PyMongo 4.0+,validator 修改后,需要重启连接或显式调式
client.admin.command("collMod", ...)生效
非结构化数据入库最麻烦的不是插入动作本身,而是字段语义漂移——今天 "score" 是整数,爬虫明天回到字符串,后天成为嵌套对象。依靠预处理规则 + 索引策略 + validator 三层卡口,少一层很容易在重跑后找到数据。