好吧,如果我说得不太清楚,请原谅我。每当我运行
'ObjectId' object is not iterable
函数时,我都会遇到这个 collections.find()
。浏览这里的答案,我不知道从哪里开始。我是编程新手,请耐心等待。
每次我点击应该从 Mongodb 获取数据的路线时,我都会得到
ValueError: [TypeError("'ObjectId' object is not iterable"), TypeError('vars() argument must have __dict__ attribute')]
。
帮助
从输出中排除“_id”。
result = collection.find_one({'OpportunityID': oppid}, {'_id': 0})
我自己也遇到了类似的问题。没有看到你的代码,我猜测回溯同样将错误跟踪到 FastAPI/Starlette 无法处理“_id”字段 - 因此你需要做的是更改结果中的“_id”字段
ObjectId
转换为字符串类型,并在返回时将字段重命名为“id”(不带下划线),以避免出现 Pydantic 问题。
首先,如果我们有一些您的代码示例,这会容易得多。我只能假设您没有正确地将 MongoDb 集合数据映射到 Pydantic BaseModel。
阅读此: MongoDB 将数据存储为 BSON。 FastAPI 将数据编码和解码为 JSON 字符串。 BSON 支持其他非 JSON 原生数据类型,包括无法直接编码为 JSON 的 ObjectId。因此,我们在将 ObjectId 存储为 _id 之前将其转换为字符串。 我想提请大家注意这个模型上的 id 字段。 MongoDB 使用 _id,但在 Python 中,属性开头的下划线具有特殊含义。如果模型上有一个以下划线开头的属性,FastAPI 使用的数据验证框架 pydantic 将假定它是私有变量,这意味着您将无法为其分配值!为了解决这个问题,我们将字段命名为 id,但给它一个别名 _id。您还需要在模型的 Config 类中将 allowed_population_by_field_name 设置为 True。
这是一个工作示例:
首先创建BaseModel:
class PyObjectId(ObjectId):
""" Custom Type for reading MongoDB IDs """
@classmethod
def __get_validators__(cls):
yield cls.validate
@classmethod
def validate(cls, v):
if not ObjectId.is_valid(v):
raise ValueError("Invalid object_id")
return ObjectId(v)
@classmethod
def __modify_schema__(cls, field_schema):
field_schema.update(type="string")
class Student(BaseModel):
id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")
first_name: str
last_name: str
class Config:
allow_population_by_field_name = True
arbitrary_types_allowed = True
json_encoders = {ObjectId: str}
现在打开所有东西:
async def get_student(student_id) -> Student:
data = await collection.find_one({'_id': student_id})
if data is None:
raise HTTPException(status_code=404, detail='Student not found.')
student: Student = Student(**data)
return student
在应用程序装饰器中使用响应模型这是示例示例
from pydantic import BaseModel
class Todo(BaseModel):
title:str
details:str
主.py
@app.get("/{title}",response_model=Todo)
async def get_todo(title:str):
response=await fetch_one_todo(title)
if not response:
raise
HTTPException(status_code=status.HTTP_404_NOT_FOUND,detail='not found')
return response
使用 db.collection.find(ObjectId:"12348901384918")
这里 db.collection 是数据库名称,字符串使用双引号。
我试图迭代所有文档,对我有用的是这个解决方案https://github.com/tiangolo/fastapi/issues/1515#issuecomment-782835977
这些行只需添加到 ObjectID 类的子类之后。以下链接给出了一个示例。 https://github.com/tiangolo/fastapi/issues/1515#issuecomment-782838556
我遇到了这个问题,直到我从 mongodb 版本 5.0.9 升级到版本 6.0.0,所以 mongodb 在其末端做了一些更改来处理这个问题(如果您有能力升级的话)! 我在创建测试服务器时遇到了这个问题,当我创建一个 6.0.0 的新测试服务器时,它修复了该错误。
好吧,所以将其添加到最上面的答案中,因为您可以在 pymongo insert 函数中运行,从而更新 python 本身内的响应字典以包含“_id”,即使它是作为参数传递的。只是新开发者可能不知道的事情。
from pymongo import *
a = {'key1':'value1'}
db1.collection1.insert(a)
print a
{'_id': ObjectId('53ad61aa06998f07cee687c3'), 'key1': 'value1'}
相关问题: 为什么在使用 pymongo 时 db.insert(dict) 将 _id 键添加到 dict 对象
文档:https://pymongo.readthedocs.io/en/stable/tutorial.html#inserting-a-document
我对编程有点陌生(在回答这个问题时已经有一年的经验了),但到目前为止我已经与 Mongo 合作过几次了。
我提出这个问题是因为我遇到了类似的问题:我需要收集文档的 ID,但是当尝试为 $oid 下标时,会弹出错误。
最简单的答案是:如果你只有 Mongo 在 _id 对象中自动设置的 ObjectId,将整个 _id 对象转换为字符串,你就会得到 ID。 至于说:
def get_ids(self) -> list:
response = []
results = self.db.collection.find()
for x in results:
id = str(x["_id"])
response.append(id)
return parse_json(response)
这样您就不会从 ObjectId 中收到错误。