Asynkron MongoDB-adgang med Motor
Forbind FastAPI til MongoDB med den asynkrone Motor-driver, og håndtér forbindelsernes livscyklus i appens lifespan.
Asynkron MongoDB-adgang med Motor er en gratis Bootcamp i FastAPI-backendudvikling-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Bootcamp i FastAPI-backendudvikling, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Bootcamp i FastAPI-backendudvikling-kurset indeholder 4 lektioner i alt.
Hvorfor Motor til asynkron MongoDB
FastAPI er et asynkront framework. Hvis du kommunikerer med MongoDB via en blokerende driver som pymongo, fryser hvert databasekald event loopet og ødelægger samtidigheden.
Motor er MongoDB's officielle asynkrone driver. Den pakker PyMongo ind og stiller coroutine-baserede metoder til rådighed, som du kan bruge med await, så event loopet fortsat kan håndtere andre forespørgsler, mens en forespørgsel er i gang.
motor.motor_asyncio.AsyncIOMotorClient— den asynkrone klient.- Alle I/O-kald (
find_one,insert_one, ...) returnerer et awaitable-objekt. - Abstraktioner på højere niveau som Beanie er bygget oven på Motor.
Installation af driveren
Installer Motor og dens afhængighed. Motor installerer automatisk en kompatibel version af PyMongo.
motor— asynkron driver.fastapioguvicorn— web-laget.
Hvis du senere vil integrere Beanie, skal du også tilføje beanie, men Motor alene er nok til at læse og skrive dokumenter direkte.
pip install motor fastapi uvicorn
# motor brings in a compatible pymongo wheel
# verify the install
python -c "import motor; print(motor.version)"Oprettelse af en asynkron klient
Du opretter én AsyncIOMotorClient til hele applikationen. Klienten administrerer en intern forbindelsespool, så du bør aldrig oprette en ny klient pr. forespørgsel.
Indeksering i klienten giver dig en database, og indeksering i databasen giver dig en samling. Intet af dette åbner en socket endnu — forbindelser oprettes først ved den første faktiske handling.
from motor.motor_asyncio import AsyncIOMotorClient
client = AsyncIOMotorClient("mongodb://localhost:27017")
database = client["shop"]
products = database["products"]
# Equivalent attribute-style access
# database = client.shop
# products = database.productsAfventning af din første forespørgsel
Da alle Motors I/O-metoder er coroutiner, skal du bruge await i en async-funktion. Hvis du glemmer await, returneres et uafklaret coroutine-objekt i stedet for dine data.
insert_one returnerer et InsertOneResult, hvis inserted_id er det genererede ObjectId. find_one returnerer det matchende dokument som en almindelig dict eller None.
import asyncio
from motor.motor_asyncio import AsyncIOMotorClient
async def main():
client = AsyncIOMotorClient("mongodb://localhost:27017")
products = client["shop"]["products"]
result = await products.insert_one({"name": "Keyboard", "price": 49})
print("inserted id:", result.inserted_id)
doc = await products.find_one({"name": "Keyboard"})
print(doc)
asyncio.run(main())Problemet med forbindelsens livscyklus
Hvor skal klienten befinde sig? Følgende muligheder kan virke fristende, men er forkerte:
- En ny klient i hver route — opbruger forbindelserne og er langsom.
- En klient på modulniveau, der oprettes ved import — opretter forbindelse, før applikationen er klar, og er svær at lukke korrekt.
Det rigtige sted er applikationens levetid: Åbn klienten, når serveren starter, gem den, og luk den, når serveren lukker ned. Det garanterer én klient med forbindelsespool pr. proces og en korrekt nedlukning.
Kontekstmanageren for applikationens levetid
Moderne FastAPI bruger en asynkron kontekstmanager, der sendes som lifespan. Kode før yield køres ved opstart, og kode efter yield køres ved nedlukning.
Gem delte ressourcer på app.state, så alle routes kan få adgang til dem. Når du kalder client.close() ved nedlukning, returneres poolens sockets korrekt til operativsystemet.
from contextlib import asynccontextmanager
from fastapi import FastAPI
from motor.motor_asyncio import AsyncIOMotorClient
@asynccontextmanager
async def lifespan(app: FastAPI):
app.state.mongo = AsyncIOMotorClient("mongodb://localhost:27017")
app.state.db = app.state.mongo["shop"]
yield
app.state.mongo.close()
app = FastAPI(lifespan=lifespan)Kontrol af forbindelsen ved opstart
Klienten opretter forbindelsen dovent, så en forkert vært ikke medfører en fejl, før den første forespørgsel. Hvis du vil fejle hurtigt ved opstart, skal du sende en letvægtskommandoen ping under opstarten.
Hvis ping-kaldet udløser en fejl, går serveren straks ned med en tydelig fejl i stedet for senere stille at levere 500-svar.
from contextlib import asynccontextmanager
from fastapi import FastAPI
from motor.motor_asyncio import AsyncIOMotorClient
@asynccontextmanager
async def lifespan(app: FastAPI):
client = AsyncIOMotorClient("mongodb://localhost:27017")
await client.admin.command("ping") # raises if unreachable
app.state.db = client["shop"]
app.state.mongo = client
yield
client.close()
app = FastAPI(lifespan=lifespan)Injektion af databasen i routes
Det fungerer at tilgå request.app.state direkte, men det kobler routes til global tilstand. Et renere mønster er en lille afhængighed, der returnerer databasehåndtaget.
Det gør routes nemme at teste — i tests kan du tilsidesætte afhængigheden, så den peger på en midlertidig database.
from fastapi import Depends, Request
from motor.motor_asyncio import AsyncIOMotorDatabase
def get_db(request: Request) -> AsyncIOMotorDatabase:
return request.app.state.db
@app.get("/products/{name}")
async def get_product(name: str, db: AsyncIOMotorDatabase = Depends(get_db)):
doc = await db["products"].find_one({"name": name})
return doc or {"error": "not found"}Serialisering af ObjectId
MongoDB-dokumenter indeholder et felt med navnet _id af typen ObjectId, som ikke kan serialiseres til JSON. Hvis du returnerer et råt dokument fra en route, udløser det en serialiseringsfejl.
Konvertér _id til en streng, før du returnerer det, eller map det til en Pydantic-model. En enkel hjælpefunktion holder dine routes rene.
def serialize(doc: dict) -> dict:
if doc and "_id" in doc:
doc["id"] = str(doc["_id"])
del doc["_id"]
return doc
# Usage inside a route:
# raw = await db["products"].find_one({"name": name})
# return serialize(raw)
print(serialize({"_id": "507f1f77bcf86cd799439011", "name": "Mouse"}))Asynkron gennemløb af markører
find() returnerer en asynkron markør, ikke en liste. Du gennemløber den med async for eller materialiserer den med to_list().
await cursor.to_list(length=100)— indlæs op til 100 dokumenter ad gangen.async for doc in cursor:— stream dokumenter ét ad gangen, hvilket er ideelt til store resultatsæt.
from fastapi import Depends
from motor.motor_asyncio import AsyncIOMotorDatabase
@app.get("/products")
async def list_products(db: AsyncIOMotorDatabase = Depends(get_db)):
cursor = db["products"].find({"price": {"$lt": 100}})
return await cursor.to_list(length=50)
# Streaming alternative:
# async for doc in cursor:
# process(doc)Konfiguration af pool og tidsgrænser
Klientens konstruktør accepterer indstillinger til finjustering. Læs dem fra miljøvariabler, så den samme kode fungerer i både udvikling og produktion.
maxPoolSize— grænse for antallet af samtidige forbindelser.serverSelectionTimeoutMS— hvor længe der ventes, før serveren erklæres utilgængelig.
Hvis URI'en indlæses fra miljøet, holdes legitimationsoplysninger også ude af kildekontrollen.
import os
from motor.motor_asyncio import AsyncIOMotorClient
def make_client() -> AsyncIOMotorClient:
uri = os.environ.get("MONGODB_URI", "mongodb://localhost:27017")
return AsyncIOMotorClient(
uri,
maxPoolSize=20,
serverSelectionTimeoutMS=5000,
)Hurtigt tjek
Hvor skal AsyncIOMotorClient oprettes og destrueres i en FastAPI-applikation?
Opsummering
Du har forbundet FastAPI med MongoDB ved hjælp af den asynkrone driver Motor:
- Motor stiller awaitable-metoder til rådighed, så MongoDB-I/O aldrig blokerer event loopet.
- Opret én
AsyncIOMotorClientpr. proces — den ejer en forbindelsespool. - Åbn og luk klienten i kontekstmanageren for applikationens levetid, og kør
pingved opstart for at fejle hurtigt. - Eksponér databasen gennem en
Depends-afhængighed, så routes bliver rene og nemme at teste. - Konvertér
_id(etObjectId) til en streng, før du returnerer JSON. - Gennemløb
find()-markører medto_list()ellerasync for, og finjustérmaxPoolSizeog tidsgrænser via miljøvariabler.
Dette fundament med Motor er præcis det, Beanie bygger videre på.
Lær Bootcamp i FastAPI-backendudvikling med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 21
- Lektioner
- 84
Ofte stillede spørgsmål
Er lektionen “Asynkron MongoDB-adgang med Motor” gratis?
Ja — alle 3 lektioner i læringssporet Bootcamp i FastAPI-backendudvikling, inklusive “Asynkron MongoDB-adgang med Motor”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Bootcamp i FastAPI-backendudvikling-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Asynkron MongoDB-adgang med Motor”?
Forbind FastAPI til MongoDB med den asynkrone Motor-driver, og håndtér forbindelsernes livscyklus i appens lifespan. Du øver dig i Bootcamp i FastAPI-backendudvikling med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Bootcamp i FastAPI-backendudvikling?
Der kræves ingen tidligere erfaring. Bootcamp i FastAPI-backendudvikling på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.
Hvor lang tid tager lektionen “Asynkron MongoDB-adgang med Motor”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Bootcamp i FastAPI-backendudvikling-lektion?
Ja. Alle Bootcamp i FastAPI-backendudvikling-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Asynkron MongoDB-adgang med Motor
- Dokumentmodellering med Beanie ODM
- Aggregationspipelines og komplekse forespørgsler
- Skemaudvikling og dokumentmigreringer