从 MongoDB Atlas 获取数据时出现“ObjectId' object is not iterable”错误

sen*_*iel 7 python api mongodb objectid

好吧,如果我没有多大意义,请原谅我。'ObjectId' object is not iterable每当我运行这些collections.find()功能时,我都会遇到这种情况。通过这里的答案,我不知道从哪里开始。我是编程新手,请多多包涵。

每次我到达应该从 Mongodb 获取数据的路线时,我都会得到ValueError: [TypeError("'ObjectId' object is not iterable"), TypeError('vars() argument must have __dict__ attribute')].

帮助

小智 9

从输出中排除“_id”。

result = collection.find_one({'OpportunityID': oppid}, {'_id': 0})
Run Code Online (Sandbox Code Playgroud)


Jam*_*son 8

我自己也遇到了类似的问题。没有看到你的代码,我猜回溯同样会追踪到 FastAPI/Starlette 无法处理“_id”字段的错误 - 因此你需要做的是将结果中的“_id”字段从 an 更改为ObjectIda string 类型并在返回时将字段重命名为“id”(不带下划线)以避免出现 Pydantic 问题。


mig*_*ike 7

首先,如果我们有一些代码示例,这会容易得多。我只能假设您没有将 MongoDb 集合数据正确映射到 Pydantic BaseModel。

\n

阅读以下内容:\n MongoDB 将数据存储为 BSON。FastAPI 将数据编码和解码为 JSON 字符串。BSON 支持其他非 JSON 原生数据类型,包括无法直接编码为 JSON 的 ObjectId。因此,我们将 ObjectId 转换为字符串,然后将它们存储为 _id。\n我想提请注意此模型上的 id 字段。MongoDB 使用 _id,但在 Python 中,属性开头的下划线具有特殊含义。如果模型上有一个以下划线开头的属性,则 pydantic\xe2\x80\x94 FastAPI\xe2\x80\x94 使用的数据验证框架将假定它是私有变量,这意味着您将无法分配它一个值!为了解决这个问题,我们将字段命名为 id,但给它一个别名 _id。您还需要在模型的 Config 类中将 allowed_population_by_field_name 设置为 True。

\n

这是一个工作示例:

\n

首先创建BaseModel:

\n
class PyObjectId(ObjectId):\n    """ Custom Type for reading MongoDB IDs """\n    @classmethod\n    def __get_validators__(cls):\n        yield cls.validate\n\n    @classmethod\n    def validate(cls, v):\n        if not ObjectId.is_valid(v):\n            raise ValueError("Invalid object_id")\n        return ObjectId(v)\n\n    @classmethod\n    def __modify_schema__(cls, field_schema):\n        field_schema.update(type="string")\n\nclass Student(BaseModel):\n    id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")\n    first_name: str\n    last_name: str\n\n    class Config:\n        allow_population_by_field_name = True\n        arbitrary_types_allowed = True\n        json_encoders = {ObjectId: str}\n
Run Code Online (Sandbox Code Playgroud)\n

现在只需解压所有内容:

\n
async def get_student(student_id) -> Student:\n    data = await collection.find_one({\'_id\': student_id})\n    if data is None:\n        raise HTTPException(status_code=404, detail=\'Student not found.\')\n    student: Student = Student(**data)\n    return student\n
Run Code Online (Sandbox Code Playgroud)\n


小智 1

使用 db.collection.find(ObjectId:"12348901384918")
这里 db.collection 是数据库名称,并使用双引号引起来的字符串。