MongoDb с FastAPI

Я немного поигрался с FastAPI и хотел подключить его к базе данных MongoDB. Я, однако, смущен, какой ODM выбрать между двигателем, который является асинхронным и mongoengine. Кроме того, в примере с NoSQL здесь они создали новый сегмент, а также вызываемый код для подключения к БД при каждом его использовании. Тем не менее, как двигатель, так и двигатель, кажется, предпочитают глобальную связь. Так, что было бы хорошим способом соединиться с mongodb?

3 ответа

Я считаю, что вы уже получили ответы на форумах по проблемам проекта Fastapi на Github: Issue 452 (закрыто). Но я резюмирую решения здесь для справок в будущем:

Короче говоря, вы можете использовать либо мотор, либо http://mongoengine.org/, Fastapi поддерживает оба, и вы можете повторно использовать глобальный клиентский объект, который запускается и завершается процессом вашего приложения.

Некоторые детали контекста (надеюсь), чтобы прояснить эти технологии и их отношения:

Официальный драйвер MongoDB для Python - pymongo. Под капотами и MongoEngine, и Motor используют Pymongo. Pymongo реализует прямого клиента для MongoDB (демонов) и предлагает Python API для выполнения запросов.

Если хотите, вы можете использовать pymongo напрямую с Fastapi. (С точки зрения SQL это было бы эквивалентно использованию psycopg2 во Flask напрямую, без использования чего-то вроде SQLAlchemy.)

MongoEngine - это ODM (средство сопоставления объектов и документов). Он предлагает объектно-ориентированный API Python, который вы можете использовать в своем приложении для более комфортной работы, а когда дело доходит до фактических запросов к БД,MongoEngine будет использовать pymongo.

Motor - это оболочка для pymongo, которая делает его неблокирующим (разрешает async / await). Он использует цикл событий либо через Tornado, либо через asyncio. Если вы используете Fastapi с uvicorn, uvicorn будет реализовывать асинхронные функции с помощью uvloop. Короче говоря, используя Motor с FastAPI, async должен "просто работать". К сожалению, в Motor не реализован ODM. В этом смысле он больше похож на пимонго.

Fastapi обрабатывает запросы от клиентов (используя Starlette), но позволит вам реализовать собственное подключение к MongoDB. Таким образом, вы не ограничены каким-либо конкретным выбором, но в основном вы сами (а-ля Flask).

Вы можете использовать хуки запуска / выключения вашего приложения FastAPI для запуска / остановки вашего клиента Motor/MongoEngine. Вам не нужно беспокоиться о том, что ваш клиентский объект не сохраняется из-за проблем с многопроцессорностью, потому что Fastapi является однопоточным.

@app.on_event("startup")
async def create_db_client():
    # start client here and reuse in future requests


@app.on_event("shutdown")
async def shutdown_db_client():
    # stop your client here

Пример реализации мотора с Fastapi можно найти здесь.

Недавно я создал Async Mongo ODM, хорошо подходящий для FastAPI: ODMantic.

app = FastAPI()
engine = AIOEngine()

class Tree(Model):
    """This model can be used either as a Pydantic model or 
       saved to the database"""
    name: str
    average_size: float
    discovery_year: int

@app.get("/trees/", response_model=List[Tree])
async def get_trees():
    trees = await engine.find(Tree)
    return trees

@app.put("/trees/", response_model=Tree)
async def create_tree(tree: Tree):
    await engine.save(tree)
    return tree

Вы можете взглянуть на пример FastAPI для получения более подробного примера.

Я не согласен с принятым ответом о том, что fastapi является однопоточным. Насколько я могу судить, fastapi является только однопоточным, если вы обрабатываете запросы с помощью асинхронной функции. Поэтому, если вы не используете асинхронность под капотом, Starlette должна использовать несколько потоков из пула потоков для обработки нескольких запросов.

Для получения дополнительной информации о модели потоков и асинхронности в fastapi/starlette это хорошее введение https://fastapi.tiangolo.com/async/

https://stackoverflow.com/questions/70446584/how-does-fastapi-uvicorn-parallelize-requests#:~:text=For%20endpoints%20defined%20with%20def%20%28not%20async%20def%29%2C,можно%20быть%20контролируемым.%20Этот%20вопрос%20%20адресован%20здесь.

Другие вопросы по тегам