Repositories in Orionjs handle data access operations, separating data access logic from business logic. They should focus exclusively on database interactions.Documentation Index
Fetch the complete documentation index at: https://www.orionjs.com/llms.txt
Use this file to discover all available pages before exploring further.
Structure and Naming
- Use
@Repository()decorator from@orion-js/mongodb - Each repository should manage a single entity type
- Follow naming convention:
{EntityNameInPlural}Repo(e.g.,UsersRepo,CardsRepo) - Put repositories in
app/{component}/repos/{EntityNameInPlural}Repo/index.ts - Collection name should be
{component_name}.{plural_of_entity}(e.g.,gaming.pokemon_cards)
Best Practices
- Keep methods simple and focused on a single responsibility
- Never access the collection directly outside the repository. All database interactions must go through repository methods. The only exception is during migrations.
- Return plain objects or domain models, not database-specific structures
- Use descriptive method names:
findById,findByEmail,create{EntityName},update{EntityName},delete{EntityName} - Avoid business logic in repositories (use services instead)
- Add proper typing for all parameters and return values
- Always use
typedId()in schema definitions for document IDs - Use
InferSchemaTypeto derive types from schemas
Naming Convention: get vs load
Use theload prefix instead of get for methods where data freshness is not guaranteed:
Use load prefix when the method:
- Uses
secondaryPreferredread preference (eventually consistent reads from replica secondaries) - Uses DataLoader methods like
loadById,loadMany(batched/deduplicated reads within request scope) - Reads from cache (in-memory, Redis, or any caching layer)
get prefix when the method:
- Reads directly from primary with no caching
- Requires guaranteed data freshness (read-after-write scenarios)
getCardsListCursor→loadCardsListCursor(usessecondaryPreferred)getCardById→loadCardById(if using DataLoader or cache)findByIdstays as is (direct primary read)
Read Preferences for Non-Critical Queries
For queries that don’t require strong consistency, use thereadPreference: 'secondaryPreferred' option to distribute read load across MongoDB replica set secondaries. This is especially important for:
- Aggregations: Heavy aggregation pipelines
- List queries: Paginated lists or search results
- Reports and analytics: Read-heavy operations for dashboards
- Count operations: Document counts for UI display
secondaryPreferred:
- When reading data immediately after a write (use primary for read-after-write consistency)
- For critical operations where stale data could cause issues
- When the query result will be used to make a write decision
Complete Example
Integration with Services
Services should inject repositories for data access:Why Use Repositories?
While repositories are functionally similar to services (both use dependency injection), they serve different purposes:- Services handle business logic, orchestration, and use cases
- Repositories focus exclusively on data access and persistence
- Cleaner code organization
- Easier testing
- Better maintainability
- Clearer dependencies