Documentmodellering met Beanie ODM
Definieer getypeerde documentmodellen, indexen en ingebedde structuren met Beanie boven op Pydantic.
Documentmodellering met Beanie ODM is een gratis Bootcamp backendontwikkeling met FastAPI-les op CoddyKit. Dit is les 2 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Bootcamp backendontwikkeling met FastAPI. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Bootcamp backendontwikkeling met FastAPI bevat in totaal 4 lessen.
Wat Beanie toevoegt aan FastAPI
Beanie is een asynchrone ODM (Object-Document Mapper) voor MongoDB, die rechtstreeks is gebouwd boven op Pydantic en de asynchrone driver motor. In een FastAPI-backend krijg je hiermee getypeerde, gevalideerde documenten die precies aanvoelen als de Pydantic-modellen die je al gebruikt voor aanvraag- en antwoordteksten.
- Elke documentklasse wordt aan één MongoDB-collectie gekoppeld.
- Elke instantie wordt aan één document gekoppeld (een JSON-achtig record).
- Validatie, serialisatie en JSON Schema krijg je automatisch dankzij Pydantic v2.
Omdat alles asynchroon is, past Beanie natuurlijk bij de asynchrone routehandlers van FastAPI en blokkeert het de eventloop niet tijdens database-I/O.
Je eerste documentmodel
Een Beanie-model erft van Document in plaats van Pydantics BaseModel. Velden worden met gewone typehints gedeclareerd en Beanie geeft elk document automatisch een veld id, dat wordt ondersteund door MongoDB's _id (een ObjectId).
- Verplichte velden hebben geen standaardwaarde; optionele velden gebruiken
Optional[...]of een standaardwaarde. - De naam van de collectie wordt afgeleid van de klassenaam, tenzij je deze overschrijft.
Hieronder wordt Product een collectie met productdocumenten.
from typing import Optional
from beanie import Document
class Product(Document):
name: str
price: float
description: Optional[str] = None
in_stock: bool = True
# An instance is just a validated Pydantic object until you insert it
item = Product(name="Keyboard", price=49.9)
print(item.name, item.price, item.in_stock)De collectie configureren met Settings
Beanie leest optionele configuratie uit een interne class Settings. De meest gebruikte optie is name, waarmee je de naam van de MongoDB-collectie expliciet instelt in plaats van op de klassenaam te vertrouwen.
name— de naam van de collectie.use_state_management— houd gewijzigde velden bij voor gedeeltelijk opslaan.validate_on_save— voer bij het opslaan van een bestaand document de validatie opnieuw uit.
Als je de naam van de collectie vastlegt, blijft je schema stabiel, zelfs als je de Python-klasse later een andere naam geeft.
from beanie import Document
class Product(Document):
name: str
price: float
class Settings:
name = "products"
validate_on_save = True
print(Product.Settings.name)Beanie initialiseren bij het opstarten van de app
Voordat een document met MongoDB kan communiceren, moet je init_beanie één keer aanroepen en je motordatabase en de lijst met documentmodellen meegeven. In FastAPI hoort dit in de handler voor de levensduur, zodat het bij het opstarten wordt uitgevoerd.
AsyncIOMotorClientmaakt de asynchrone verbinding.document_modelsregistreert elk model, zodat Beanie indexen en queries kan opbouwen.
Dit is configuratie voor de infrastructuur van framework en server — er is een actieve MongoDB voor nodig. Beschouw het daarom als een configuratiepatroon, niet als een zelfstandig script.
from contextlib import asynccontextmanager
from fastapi import FastAPI
from motor.motor_asyncio import AsyncIOMotorClient
from beanie import init_beanie
@asynccontextmanager
async def lifespan(app: FastAPI):
client = AsyncIOMotorClient("mongodb://localhost:27017")
await init_beanie(
database=client.shop_db,
document_models=[Product],
)
yield
client.close()
app = FastAPI(lifespan=lifespan)Veldvalidatie met Pydantic
Omdat een Document een Pydantic-model is, werken alle validatiehulpmiddelen die je kent nog steeds: beperkingen met Field, aangepaste validators en uitgebreide typen zoals EmailStr of HttpUrl.
Field(gt=0)wijst niet-positieve prijzen af.Field(min_length=...)dwingt een tekenreekslengte af.- Validatie wordt uitgevoerd wanneer het object wordt gemaakt, zodat onjuiste gegevens MongoDB nooit bereiken.
Dit fragment gebruikt uitsluitend validatie in Pydantic-stijl en kan zelfstandig worden uitgevoerd.
from pydantic import BaseModel, Field, ValidationError
class Product(BaseModel):
name: str = Field(min_length=1, max_length=80)
price: float = Field(gt=0)
sku: str = Field(pattern=r"^[A-Z]{3}-\d{4}$")
try:
Product(name="Mouse", price=-5, sku="bad")
except ValidationError as e:
print("Rejected:", len(e.errors()), "errors")
good = Product(name="Mouse", price=19.99, sku="MOU-0001")
print("Accepted:", good.sku)Indexen declareren met Indexed
Indexen maken queries snel en kunnen uniciteit afdwingen. Beanie biedt hiervoor twee stijlen. De eenvoudigste is de wrapper Indexed rond het type van een veld, waarmee een index voor één veld wordt gemaakt.
Indexed(str, unique=True)maakt een unieke index — ideaal voor een e-mailadres of SKU.- Beanie maakt de index automatisch tijdens
init_beanie.
Gebruik unieke indexen om integriteitsregels in de database af te dwingen in plaats van alleen op controles in de applicatie te vertrouwen.
import pymongo
from beanie import Document, Indexed
from pydantic import EmailStr
class User(Document):
email: Indexed(EmailStr, unique=True)
username: Indexed(str)
age: int
class Settings:
name = "users"Samengestelde indexen in Settings
Voor indexen met meerdere velden of geavanceerde indexen declareer je ze in Settings.indexes met PyMongo's IndexModel. Zo maak je samengestelde indexen, bepaal je de sorteerrichting of voeg je een TTL toe.
- Geef de velden met hun richtingen op:
pymongo.ASCENDING/DESCENDING. - Geef
unique=TrueofexpireAfterSeconds=...door via deIndexModel.
De volgorde is belangrijk: een samengestelde index op (category, price) optimaliseert queries die op categorie filteren en daarna op prijs sorteren.
import pymongo
from pymongo import IndexModel
from beanie import Document
class Product(Document):
name: str
category: str
price: float
class Settings:
name = "products"
indexes = [
IndexModel(
[("category", pymongo.ASCENDING), ("price", pymongo.DESCENDING)],
name="category_price_idx",
),
]Ingesloten documenten met BaseModel
MongoDB slaat geneste objecten op binnen één document. In Beanie is een ingesloten structuur gewoon een normaal Pydantic-BaseModel dat als veldtype wordt gebruikt — het is geen afzonderlijke collectie en heeft geen id.
- Sluit gegevens in wanneer de geneste gegevens bij het bovenliggende object horen en altijd samen worden gelezen (zoals een adres in een gebruiker).
- De volledige structuur wordt als één document gevalideerd en geserialiseerd.
Hier is Address ingesloten in het User-document.
from pydantic import BaseModel
from beanie import Document
class Address(BaseModel):
street: str
city: str
postal_code: str
class User(Document):
name: str
address: Address
class Settings:
name = "users"
u = User(name="Ada", address=Address(street="1 Main", city="Oslo", postal_code="0150"))
print(u.address.city)Lijsten met ingesloten structuren
Een documentveld kan een lijst met ingesloten modellen bevatten. Dat is ideaal voor één-op-veelgegevens die volledig bij het bovenliggende document horen, zoals orderregels of opmerkingen.
list[OrderItem]valideert elk element tijdens het aanmaken.- Elk item wordt inline geserialiseerd, dus voor het lezen van de order is geen extra query nodig.
Gebruik bij voorkeur ingesloten lijsten wanneer de verzameling begrensd is en samen met het bovenliggende document wordt gelezen; gebruik verwijzingen wanneer de verzameling onbeperkt kan groeien.
from pydantic import BaseModel
from beanie import Document
class OrderItem(BaseModel):
product_name: str
quantity: int
unit_price: float
class Order(Document):
customer: str
items: list[OrderItem]
class Settings:
name = "orders"
@property
def total(self) -> float:
return sum(i.quantity * i.unit_price for i in self.items)
order = Order(
customer="Lin",
items=[OrderItem(product_name="Pen", quantity=3, unit_price=1.5)],
)
print(order.total)Verwijzen naar andere documenten met Link
Wanneer gerelateerde gegevens in een eigen verzameling staan en gedeeld of groot zijn, gebruik je een verwijzing in plaats van insluiting. Beanie's Link[OtherDocument] slaat een verwijzing (een DBRef) op en kan het gekoppelde document op aanvraag ophalen.
Link[Category]houdt de categorie in een eigen verzameling.- Gebruik
fetch_links=Trueop een query, ofawait doc.fetch_link(...), om de verwijzing op te lossen.
Vuistregel: sluit gegevens in die eigendom zijn van het document en samen worden gelezen; verwijs naar gedeelde gegevens of gegevens die afzonderlijk worden bevraagd.
from beanie import Document, Link
class Category(Document):
name: str
class Settings:
name = "categories"
class Product(Document):
name: str
price: float
category: Link[Category]
class Settings:
name = "products"Modelleerkeuzes: insluiten versus verwijzen
De belangrijkste ontwerpkeuze bij het modelleren van documenten is of je gegevens insluit of ernaar verwijst. Er is geen universeel antwoord: het hangt af van de gebruikspatronen en de omvang van de gegevens.
- Sluit in wanneer: het kind bij het bovenliggende document hoort, altijd samen wordt geladen en een begrensde omvang heeft (adres, orderregels).
- Verwijs wanneer: de gegevens in meerdere documenten worden gedeeld, zelfstandig worden bevraagd of onbeperkt kunnen groeien (categorieën, auteurs, auditlogboeken).
MongoDB-documenten hebben een limiet van 16 MB, dus onbeperkt groeiende ingesloten arrays lopen uiteindelijk tegen die limiet aan. Dat is nog een reden om naar grote, groeiende verzamelingen te verwijzen.
Korte controle: insluiten of verwijzen?
Je modelleert een e-commercebackend met Beanie. Een Product hoort precies bij één Category, categorieën worden gedeeld door duizenden producten en je toont regelmatig alle categorieën op een eigen beheerpagina.
Samenvatting: documenten modelleren met Beanie
Je hebt geleerd hoe je MongoDB-gegevens modelleert met Beanie boven op Pydantic:
- Subklassen van Document koppelen een Python-klasse aan een verzameling;
class Settingsstelt de naam en opties van de verzameling in. init_beaniemoet bij het opstarten worden uitgevoerd (in de levensduur van FastAPI), samen met je motordatabank endocument_models.- Beperkingen en validators van Pydantic
Fieldhouden ongeldige gegevens uit de databank. - Maak indexen met de wrapper
Indexedvoor afzonderlijke velden, of metSettings.indexes+IndexModelvoor samengestelde en unieke indexen. - Sluit gegevens die eigendom zijn van het document, begrensd zijn en samen worden gelezen in als geneste
BaseModels; verwijs metLink[...]naar gedeelde of groeiende gegevens en houd rekening met de documentlimiet van 16 MB.
Met deze hulpmiddelen kun je getypeerde, gevalideerde en efficiënt bevraagbare MongoDB-schema's ontwerpen voor je FastAPI-backend.
Leer Bootcamp backendontwikkeling met FastAPI met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 21
- Lessen
- 84
Veelgestelde vragen
Is de les “Documentmodellering met Beanie ODM” gratis?
Ja — je kunt hier op het web alle 3 lessen van het leerpad Bootcamp backendontwikkeling met FastAPI, waaronder “Documentmodellering met Beanie ODM”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Bootcamp backendontwikkeling met FastAPI bevat in totaal 4 lessen.
Wat leer ik in “Documentmodellering met Beanie ODM”?
Definieer getypeerde documentmodellen, indexen en ingebedde structuren met Beanie boven op Pydantic. Je oefent met Bootcamp backendontwikkeling met FastAPI door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Bootcamp backendontwikkeling met FastAPI te beginnen?
Ervaring vooraf is niet nodig. Bootcamp backendontwikkeling met FastAPI op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.
Hoe lang duurt de les “Documentmodellering met Beanie ODM”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Bootcamp backendontwikkeling met FastAPI?
Ja. Elke les over Bootcamp backendontwikkeling met FastAPI bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Asynchrone MongoDB-toegang met Motor
- Documentmodellering met Beanie ODM
- Aggregatiepipelines en complexe queries
- Schema-evolutie en documentmigraties