Skip to content

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.