mongodb操作需严格类型校验:datetime须为原生实例并显式转换;objectid字符串须转为objectid实例且先验证合法性;浮点数精度敏感场景应改用decimal128;嵌套字典中none字段需统一处理避免结构不一致。

插入前检查 datetime 是否为 datetime.datetime 实例
MongoDB 驱动(如 pymongo)只接受原生 datetime.datetime 或 datetime.date,传入字符串、time.struct_time、或第三方时间类型(如 pendulum.DateTime、arrow.Arrow)会直接抛 TypeError: cannot encode object。别指望自动转换——驱动不做猜测。
- 用
isinstance(obj, datetime.datetime)显式判断,不是就转:datetime.datetime.fromisoformat(s)(ISO字符串)、datetime.datetime.utcfromtimestamp(ts)(时间戳) -
date类型同理:isinstance(obj, datetime.date),非原生就用datetime.date.fromisoformat() - 特别注意 Pandas 的
Timestamp:它不是datetime子类,必须调用.to_pydatetime()或.to_datetime64().astype(datetime.datetime)
ObjectId 字段误传字符串导致查询无声失败
把 "60a1b2c3d4e5f67890123456" 当作 ObjectId 直接塞进 find({"_id": "..."}) 不报错,但查不到数据——因为 MongoDB 把它当普通字符串匹配,而真实 _id 是 ObjectId 类型。这是最隐蔽的“类型错误”。
- 查前强制转换:
from bson import ObjectId,然后find({"_id": ObjectId(id_str)}) - 插入时也别手动生成字符串 ID;用
ObjectId()生成新值,或确保传入的是ObjectId实例 - 校验字符串格式:用
ObjectId.is_valid(id_str)判断是否合法,再转,避免InvalidId异常
浮点数精度丢失引发的写入/查询不一致
Python float 在序列化为 BSON 时可能被截断(尤其高精度小数),导致写入后读出来值变了,比如 3.141592653589793 变成 3.1415926535897931。这不是异常,但会影响数值比较和聚合结果。
- 对精度敏感场景(金融、科学计算),改用
Decimal:先from decimal import Decimal,再存为字符串或自定义编码(BSON 不原生支持Decimal,需用decimal128类型) - 启用
decimal128:from bson.decimal128 import Decimal128,存为Decimal128(str(d));查出来是Decimal128实例,需调用.to_decimal() - 别依赖
float做等值查询,改用范围查询({"price": {"$gte": 99.99, "$lte": 100.01}})
嵌套字典里混入 None 和空字典导致字段缺失
pymongo 默认跳过值为 None 的字段(类似 Python 的 None → BSON null,但某些版本或配置下会被忽略),而空字典 {} 会被写入。这造成结构不一致:同一字段有时不存在,有时存在但为空对象。
- 统一用
dict.setdefault(key, {})或显式赋值,避免None进入文档 - 插入前做清理:
{k: v for k, v in data.items() if v is not None},但注意这会删掉有意设为None的字段 - 更稳妥:用
ReplaceOne+upsert=True替代insert_one,配合$setOnInsert控制默认值
ObjectId 字符串没转就去查,以及 datetime 来自 Pandas 或 API 响应却没归一化。这两处不报错,但数据对不上,得盯日志、打日志、对比原始输入和 collection.find_one() 返回值。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











