Use Case 6: Multi-Model Service with Registration
Scenario: A social app manages users, posts, and comments. Each has its own model, repository, and indexes โ registered centrally and initialized at startup.
๐ฆ What's New?
| Component | Description |
|---|---|
ModelRegistry.register |
One call per collection โ model + indexes together. |
ModelRegistry.initialize_all |
Creates every registered index at startup (idempotent). |
| Repositories | One repository class per collection, all sharing the same connection. |
๐ Example
Python
from contextlib import asynccontextmanager
from fastapi import FastAPI
from mongo_ops import BaseDocument, BaseRepository, ModelRegistry, MongoConnectionManager
class User(BaseDocument):
username: str = ""
email: str = ""
role: str = "user"
class Post(BaseDocument):
title: str = ""
content: str = ""
author_id: str = ""
likes: int = 0
class Comment(BaseDocument):
post_id: str = ""
user_id: str = ""
content: str = ""
class UserRepository(BaseRepository[User]):
def __init__(self):
super().__init__("users", User)
class PostRepository(BaseRepository[Post]):
def __init__(self):
super().__init__("posts", Post)
class CommentRepository(BaseRepository[Comment]):
def __init__(self):
super().__init__("comments", Comment)
# ---------------------------
# Central registration + indexes
# ---------------------------
ModelRegistry.register("users", User, indexes=[("email", 1), ("username", 1)])
ModelRegistry.register("posts", Post, indexes=[("author_id", 1), ("created_at", -1)])
ModelRegistry.register("comments", Comment, indexes=[("post_id", 1), ("user_id", 1)])
# ---------------------------
# Lifecycle
# ---------------------------
@asynccontextmanager
async def lifespan(_app: FastAPI):
async with MongoConnectionManager.lifespan(
uri="mongodb://localhost:27017", db_name="social_app"
):
await ModelRegistry.initialize_all()
yield
app = FastAPI(lifespan=lifespan)
# Created after connect() โ inside the lifespan body is fine, or use a dependency.
user_repo = UserRepository()
post_repo = PostRepository()
comment_repo = CommentRepository()
@app.post("/users/", response_model=User)
async def create_user(user: User):
return await user_repo.create(user)
@app.post("/posts/", response_model=Post)
async def create_post(post: Post):
return await post_repo.create(post)
@app.post("/comments/", response_model=Comment)
async def create_comment(comment: Comment):
return await comment_repo.create(comment)
๐ก Tips
- Place
user_repo = ...inside the lifespan/after connect. Module-level instantiation beforeconnect()raisesRuntimeError("Database not connected..."). - Model relationships here are plain
ObjectIdstrings stored on the child docs. To resolve them on read, see use case 08 โ Population. - Registering indexes on
created_at/author_id/post_idkeeps the common queries indexed (see use case 13).