How can I use MongoDB using libraries such a pymongo or MongoEngine?
I tried to create a basic project with pymongo, but when I try to return MongoDB entity using .find_one() for example, I got an error that ... ObjectId does not iterable....
Then I tried MongoEngine, but when I return for example Article.objects, it just returns "_cls": "".
Is it possible to use MongoDB in FastAPI or I can use only SQLAlchemy?
I also found similar issues in a repo and some answers on StackOverflow but doesn't found how to return MongoDB entities in fastapi responses.
As far as I know there's nothing in fastAPI that requires SQLAlchemy, i myself use asyncpg
Can you please post an example of your code?
Barring that I would imagine you need to use their json utilility to get what you want, python doesn't know how to encode ObjectId which is an object returned by the mongo response https://api.mongodb.com/python/current/api/bson/json_util.html
Personally I'd write a Custom Response class that encapsulates this. Something like MongoJSONResponse an example of one that already exists and usage can be found here. https://fastapi.tiangolo.com/advanced/custom-response/#orjsonresponse
Small example:
from fastapi import FastAPI
from mongoengine import *
connect('FastAPILearn')
app = FastAPI()
class HumanDB(Document):
name = StringField(max_length=120)
age = IntField(min_value=0)
@app.get("/users")
def get_users():
return {'data': HumanDB.objects.all()}
@app.get("/user")
def get_user():
return {'data': HumanDB.objects.first()}
First method cause ServerError with output RecursionError: maximum recursion depth exceeded in comparison and second returns {"data":{"_cls":"HumanDB"}} response.
I found some workaround, but it seems to be very dirty.
class HumanDB(Document):
name = StringField(max_length=120)
age = IntField(min_value=0)
def to_dict(self):
return {'id': str(self.id),
'name': self.name,
'age': self.age}
@app.get("/users")
def get_users():
return {'data': list(map(lambda h: h.to_dict(), HumanDB.objects))}
@app.get("/user")
def get_user():
return {'data': HumanDB.objects.first().to_dict()}
Have you tried using the json utils described above https://api.mongodb.com/python/current/api/bson/json_util.html I truly think that's the solution to your problem. You need a serializer that understands mongo objects, that serializer does.
You are getting this error
... ObjectId does not iterable....
because Mongo's _id field is a bytes object. you can circumvent this by suppressing the _id field when you return it.
return col.find_one({ 'field' : 'value' }, {'_id': 0})
Thanks for the help here everyone! :clap: :bow:
I assume you solved your problem, so thanks for reporting back and closing the issue @KirillSaltykov :+1:
Most helpful comment
Have you tried using the json utils described above https://api.mongodb.com/python/current/api/bson/json_util.html I truly think that's the solution to your problem. You need a serializer that understands mongo objects, that serializer does.