art049 / art049/odmantic

Suggested Documentation Fix

Open
#233 1 comment 0 reactions 0 assignees View on GitHub
feature
Dominant language
Python
Stars
1.2k
Forks
97
PR merge metrics
No merged PRs in 30d

Description

# Feature request

### Context

Currently, it is suggested that we globally set the engine at the module level, and I suggest that this be removed from the documentation. Mongo suggests that you scale horizontally, actually, all NoSQL solutions should scale horizontally. Therefore, you can have many databases with the same data, just organized based on some other key. Like year, month, week, etc. If we call the engine at the global level, you remove the ability to control this properly.

### Solution

I suggest that this be removed from the documentation. If it were SQL, we have a different situation here. SQL is vertically scalable, so a global call is possible. But for mongo, the solution that I am using looks like this:

```python
from typing import Any, Iterator
from bson import ObjectId

from odmantic import AIOEngine, Model
from pydantic import BaseModel

class PyObjectId(ObjectId):
@classmethod
def __get_validators__(cls) -> Iterator:
yield cls.validate

@classmethod
def validate(cls, v: Any) -> ObjectId:
if not ObjectId.is_valid(v):
raise ValueError("Invalid objectid")
return ObjectId(v)

@classmethod
def __modify_schema__(cls, field_schema: Any) -> None:
field_schema.update(type="string")

class Entries(Model):
rank: int
username: str
points: float
contest_id: str

class CreateEntriesModel(BaseModel):
rank: int
username: str
points: float
contest_id: str
season: int

class Config:
allow_population_by_field_name = True
arbitrary_types_allowed = True
json_encoders = {ObjectId: str}
schema_extra = {
"example": {
"rank": "1",
"username": "minervaengineering",
"points": "199.15",
"contest_id": "123456789",
"season": "2022"
}
}

@router.post("/", response_description="Add new entry", response_model=Entries)
async def create_entry(entry: CreateEntriesModel):
engine = AIOEngine(motor_client=client, database=f"ContestEntries_{entry.season}")
entry = Entries(
rank=entry.rank,
username=entry.username,
points=entry.points,
contest_id=entry.contest_id
)
await engine.save(entry)
return entry
```

#### Alternative solutions

I attempted to make the global call work, but it's a sketchy solution. And really, unstable. This is a basic setup I decided to rainman on for the last 3 hours. it's now past 2am here, and I quite literally don't know why I felt the need to do this. You did a great job on this package, and I'd love for this to be truly scalable, and for others to not run into a brick wall because of the documentation.

### Additional context

That's all! Good work!

Contributor guide

Open the contributing guide

Research direction

The issue does not name a documentation file; first search the docs for the recommendation to set the engine globally and review the AIOEngine example using a season-specific database. Done means the documentation no longer presents global engine setup as the recommended approach and accurately reflects the database-per-context concern described here.

Written by the indexing model from the issue text.

Assessment

Tech stack
mongodb, python
Domain
databases, documentation
Issue type
Documentation
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.