Database Overview
Database
Uses Amazon DocumentDB (MongoDB-compatible).
Connections go through Beanie (Motor); the default database name is jester.
Table List
| Table | Description |
|---|---|
| article | "10-second race result summary" articles tied to races (auto racing, keirin, horse racing). Manages title, body, publication status, etc. |
| category | Blog categories. Also used by blog_builder to pick the article template |
| media | Uploaded media files (images, videos) and AI-generated thumbnail images |
| ng_word | Prohibited words checked against generated text |
| auto_racing | Auto racing race information, race results, and AI predictions |
| bicycle_racing | Keirin race information, race results, and AI predictions |
| horse_racing | Horse racing race information, race results, and AI predictions |
| old_blog | Past blog articles targeted for migration (input for rewriting) |
| blog | AI-generated blog articles (rewrites of past blogs, or newly written race recaps/predictions) |
Common Rules
| Rule | Details |
|---|---|
| Primary key | _id (ObjectId auto-generated by DocumentDB; however, racing tables (auto_racing / bicycle_racing / horse_racing) store the external race ID) |
| Datetime fields | Managed as UNIX timestamps (milliseconds) |
| Deletion method | Soft delete (managed via the deleted_at field) |
| Array fields | Stored as native DocumentDB arrays |
| List retrieval | Sorted by updated_at by default (racing tables sort by name) |
Exception to soft delete
article / blog records that fail mid-generation (left with status=generating and an empty body)
are hard-deleted, but only when the SQS delivery that failed was the final attempt. Incomplete
artifacts that will never be published get in the way of regeneration if they linger in the list.
Note that article no longer hard-deletes on generation failure: it is marked status=failed with the
reason kept in generation_error (hard delete remains only for article_builder build failures).
How race information is stored
Race information is split into three collections by racing type: auto_racing / bicycle_racing /
horse_racing. The _id (the race_id inside the race result JSON) is unique across racing types,
and the API (/v1/races) searches all three collections to locate a race. Because the racing type is
expressed by the collection itself, race documents do not carry a type field.