我在通過 FastAPI 插入 MongoDB 時遇到一些問題。
下面的代碼按預期作業。請注意response變數未在response_to_mongo().
這model是一個 sklearn ElasticNet 模型。
app = FastAPI()
def response_to_mongo(r: dict):
client = pymongo.MongoClient("mongodb://mongo:27017")
db = client["models"]
model_collection = db["example-model"]
model_collection.insert_one(r)
@app.post("/predict")
async def predict_model(features: List[float]):
prediction = model.predict(
pd.DataFrame(
[features],
columns=model.feature_names_in_,
)
)
response = {"predictions": prediction.tolist()}
response_to_mongo(
{"predictions": prediction.tolist()},
)
return response
但是,當我predict_model()這樣寫并將response變數傳遞給response_to_mongo():
@app.post("/predict")
async def predict_model(features: List[float]):
prediction = model.predict(
pd.DataFrame(
[features],
columns=model.feature_names_in_,
)
)
response = {"predictions": prediction.tolist()}
response_to_mongo(
response,
)
return response
我收到一條錯誤訊息,指出:
TypeError: 'ObjectId' object is not iterable
從我的閱讀來看,這似乎是由于 FastAPI 和 Mongo 之間的 BSON/JSON 問題。但是,當我不使用變數時,為什么它在第一種情況下起作用?這是由于 FastAPI 的異步特性造成的嗎?
uj5u.com熱心網友回復:
根據檔案:
插入檔案時
"_id",如果檔案尚未包含鍵,則會自動添加特殊鍵 ,"_id"。的值"_id"在整個集合中必須是唯一的。回傳InsertOneResultinsert_one()的一個實體。有關“_id”的更多資訊,請參閱 有關 _id 的檔案。
因此,在第二種情況下,當您將字典傳遞給insert_one()函式時,Pymongo 將向您的字典添加ObjectId從資料庫中檢索資料所需的唯一識別符號(即 );因此,當從端點回傳回應時,ObjectId序列化失敗(默認情況下,FastAPI 使用 序列化資料jsonable_encoder并回傳 a JSONResponse)。
解決方案 1
在回傳之前"_id"從字典中洗掉鍵(請參閱此處了解如何從字典中洗掉鍵):response
response.pop('_id', None)
解決方案 2
將加載的字串轉儲BSON為有效JSON字串,然后將其作為 dict 重新加載,如此處和此處所述。
from bson import json_util
import json
response = json.loads(json_util.dumps(response))
解決方案 3
定義一個自定義,JSONEncoder如下所述:
import json
from bson import ObjectId
class JSONEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, ObjectId):
return str(o)
return json.JSONEncoder.default(self, o)
response = JSONEncoder().encode(response)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/444041.html
