我正在玩一些FastAPI并想将它连接到 MongoDB 数据库。然而,我很困惑在异步电机和 mongoengine 之间选择哪个 ODM。此外,在这里的 NoSQL 示例中,他们创建了一个新的存储桶,并且每次使用它时都调用了连接到 db 的代码。但是,motor 和 mongoengine 似乎都更喜欢全局连接。那么连接mongodb的好方法是什么?
2 回答
我相信你已经在 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 连接。因此,您不受任何特定选择的限制,但您大部分时间都靠自己(a la 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 实现电机的示例。
我最近创建了一个非常适合 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 示例以获得更详细的示例。