You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决PyObjectId存入MongoDB时被转为字符串而非ObjectId的问题?

解决MongoDB存储ObjectId而非字符串的问题

你的问题核心在于PyObjectId类的序列化配置强制将ObjectId转换为字符串,导致存入MongoDB时无法保留原生ObjectId类型。以下是具体修复方案:

1. 修改PyObjectId的序列化逻辑

当前代码中serialization参数固定将ObjectId转为字符串,需要调整为仅在JSON序列化时转字符串,Python对象层面保留ObjectId实例:

from typing import Any
from bson import ObjectId
from pydantic_core import core_schema
from pydantic import BaseModel, Field
from datetime import datetime


class PyObjectId(ObjectId):
    """To create a pydantic Object that validates bson ObjectID"""

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> core_schema.CoreSchema:
        return core_schema.json_or_python_schema(
            json_schema=core_schema.str_schema(),
            python_schema=core_schema.union_schema(
                [
                    core_schema.is_instance_schema(ObjectId),
                    core_schema.chain_schema(
                        [
                            core_schema.str_schema(),
                            core_schema.no_info_plain_validator_function(cls.validate),
                        ]
                    ),
                ]
            ),
            # 修改序列化逻辑:Python环境输出原生ObjectId,JSON环境输出字符串
            serialization=core_schema.plain_serializer_function_ser_schema(
                lambda x: str(x) if core_schema.is_json_serialization() else x
            ),
        )

    @classmethod
    def validate(cls, value) -> ObjectId:
        if not ObjectId.is_valid(value):
            raise ValueError("Invalid ObjectId")
        return ObjectId(value)


class GoalRecordStored(BaseModel):
    """Goal Record Model."""

    player_id: PyObjectId = Field(..., validation_alias="Player ID")
    date: datetime = Field(validation_alias="Date")

2. 存入MongoDB时使用正确的序列化模式

调用model_dump时,指定mode='python'以保留Python原生类型(包括ObjectId),同时加上by_alias=True确保使用MongoDB需要的字段别名:

# 示例:创建实例并存入MongoDB
record = GoalRecordStored(**{"Player ID": "60d21b4667d0d8992e610c85", "Date": datetime.now()})
# 生成适合MongoDB的字典
mongo_data = record.model_dump(by_alias=True, mode='python')
# 存入MongoDB(假设已有collection实例)
collection.insert_one(mongo_data)

验证效果

执行上述代码后,MongoDB中的Player ID字段将以ObjectId类型存储,而非字符串。你可以通过MongoDB客户端查看字段类型确认。

内容的提问来源于stack exchange,提问作者ProxilityProblemSolver

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 17:21:07