带有 FastAPI 的 MongoDb

Posted

技术标签:

【中文标题】带有 FastAPI 的 MongoDb【英文标题】:MongoDb with FastAPI 【发布时间】:2019-12-25 00:45:08 【问题描述】:

我正在玩FastAPI 并想将它连接到 MongoDB 数据库。然而,我很困惑在异步电机和 mongoengine 之间选择哪个 ODM。此外,在 NoSQL 示例 here 中,他们创建了一个新存储桶,并且每次使用它时都调用了连接到 db 的代码。但是,motor 和 mongoengine 似乎都更喜欢全局连接。那么连接mongodb的好方法是什么?

【问题讨论】:

【参考方案1】:

相信您已经在 Github 上的 Fastapi 项目的问题论坛中得到了答案:Issue 452 (closed)。但我将在这里回顾一下解决方案以供将来参考:

简而言之,您可以使用motor 或mongoengine,Fastapi 支持两者,并且您可以重用以您的应用进程开始和结束的全局客户端对象。

一些上下文细节(希望)阐明这些技术及其关系:

Python 的官方 MongoDB 驱动程序是 pymongo。在引擎盖下,MongoEngine 和 Motor 都使用 Pymongo。 Pymongo 为 MongoDB(守护进程)实现了一个直接客户端,并提供了一个 Python API 来发出请求。

如果你愿意,你可以直接使用 pymongo 和 Fastapi。 (在 SQL 方面,这相当于直接在 Flask 中使用 psycopg2 而无需通过 SQLAlchemy 之类的东西。)

MongoEngine 是一个 ODM(对象-文档映射器)。它提供了一个 Python 面向对象的 API,您可以在应用程序中使用它来更舒适地工作,当涉及到实际的 DB 请求时,MongoEngine 将使用 pymongo。

Motor 是 pymongo 的包装器,使其成为非阻塞(允许异步/等待)。它使用事件循环,通过 Tornado 或通过 asyncio。如果你将 Fastapi 与 uvicorn 一起使用,uvicorn 将使用 uvloop 实现异步功能。简而言之,将 Motor 与 FastAPI 一起使用,异步应该“正常工作”。不幸的是,Motor 没有实现 ODM。从这个意义上说,它更类似于 pymongo。

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

可以在here找到一个使用 Fastapi 实现电机的示例。

【讨论】:

【参考方案2】:

我最近创建了一个非常适合 FastAPI 的 Async Mongo ODM: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 example 以获得更详细的示例。

【讨论】:

以上是关于带有 FastAPI 的 MongoDb的主要内容,如果未能解决你的问题,请参考以下文章

带有 FastAPI 的 MongoDb

带有用户名和角色的 FastAPI 发布请求,怎么做?

fastapi swagger 不发送带有 url 的令牌

对于带有 json 列的 sqlite db,fastapi 响应的格式不正确

Asyncio:带有 aio-pika 的 Fastapi,消费者忽略 Await

您将如何使用带有 FastAPI 的 asyncpg 将选择查询的返回值映射到 pydantic 模型以进行输出和验证?