ODMs and Mongo-style adapters¶
Paramora's Mongo backend already emits normal MongoDB filter dictionaries and sort pairs. Many ODMs can consume those directly or with a small adapter.
For convenience, Paramora includes MongoOdmEmitter, which wraps the regular Mongo output and exposes common helper formats for ODMs such as Beanie and MongoEngine.
Install¶
The adapter itself has no extra runtime dependency:
If your application uses an ODM, install that ODM separately:
Mongo ODM adapter example¶
from typing import Annotated
from fastapi import Depends, FastAPI
from paramora import CompiledQuery, Query, QueryContract, query_field
from paramora.emitters.odm import MongoOdmEmitter, MongoOdmQuery
class ItemQuery(QueryContract):
status: Annotated[str, query_field("eq", "in")]
created_at: Annotated[str, query_field("eq", sortable=True)]
item_query: Query[MongoOdmQuery] = Query(
ItemQuery,
emitter=MongoOdmEmitter(),
)
app = FastAPI()
@app.get("/items")
def list_items(query: CompiledQuery[MongoOdmQuery] = Depends(item_query)):
mongo = query.output
return {
"filter": mongo.filter,
"beanie_sort": mongo.beanie_sort(),
"limit": mongo.limit,
"offset": mongo.offset,
}
Beanie-style sort helper¶
compiled = item_query.parse({"status__in": "free,busy", "sort": "-created_at"})
odm = compiled.output
assert odm.filter == {"status": {"$in": ["free", "busy"]}}
assert odm.beanie_sort() == ("-created_at",)
MongoEngine-style order helper¶
compiled = item_query.parse({"sort": "-created_at"})
odm = compiled.output
assert odm.mongoengine_order_by() == ("-created_at",)
Why this is adapter-based¶
Mongo ODMs differ in how they represent queries, sessions, projections, eager loading, and execution. Paramora therefore does not try to own the ODM query lifecycle.
The safe boundary is:
- Paramora validates HTTP query parameters.
- Paramora compiles them into Mongo-compatible filter/sort/pagination data.
- Your application passes that data into the ODM in the way that best matches your model and session lifecycle.