Implement hybrid filtering strategy for parks and rides

- Added comprehensive documentation for hybrid filtering implementation, including architecture, API endpoints, performance characteristics, and usage examples.
- Developed a hybrid pagination and client-side filtering recommendation, detailing server-side responsibilities and client-side logic.
- Created a test script for hybrid filtering endpoints, covering various test cases including basic filtering, search functionality, pagination, and edge cases.
This commit is contained in:
pacnpal
2025-09-14 21:07:17 -04:00
parent 0fd6dc2560
commit 35f8d0ef8f
42 changed files with 8490 additions and 224 deletions

View File

@@ -319,7 +319,136 @@ The moderation system provides comprehensive content moderation, user management
## Rides API
### Rides Listing
### Hybrid Rides Filtering (Recommended)
The hybrid filtering system automatically chooses between client-side and server-side filtering based on data size for optimal performance.
#### Main Hybrid Endpoint
- **GET** `/api/v1/rides/hybrid/`
- **Description**: Intelligent ride filtering with automatic strategy selection
- **Strategy Selection**:
- ≤200 total records: Client-side filtering (loads all data for frontend filtering)
- >200 total records: Server-side filtering (database filtering with pagination)
- **Query Parameters** (25+ comprehensive filtering options):
- `search` (string): Full-text search across ride names, descriptions, parks, and related data
- `park_slug` (string): Filter by park slug
- `park_id` (int): Filter by park ID
- `categories` (string): Filter by ride categories (comma-separated): RC,DR,FR,WR,TR,OT
- `statuses` (string): Filter by ride statuses (comma-separated)
- `manufacturer_ids` (string): Filter by manufacturer IDs (comma-separated)
- `designer_ids` (string): Filter by designer IDs (comma-separated)
- `ride_model_ids` (string): Filter by ride model IDs (comma-separated)
- `opening_year` (int): Filter by specific opening year
- `min_opening_year` (int): Filter by minimum opening year
- `max_opening_year` (int): Filter by maximum opening year
- `min_rating` (number): Filter by minimum average rating (1-10)
- `max_rating` (number): Filter by maximum average rating (1-10)
- `min_height_requirement` (int): Filter by minimum height requirement in inches
- `max_height_requirement` (int): Filter by maximum height requirement in inches
- `min_capacity` (int): Filter by minimum hourly capacity
- `max_capacity` (int): Filter by maximum hourly capacity
- `roller_coaster_types` (string): Filter by roller coaster types (comma-separated)
- `track_materials` (string): Filter by track materials (comma-separated): STEEL,WOOD,HYBRID
- `launch_types` (string): Filter by launch types (comma-separated)
- `min_height_ft` (number): Filter by minimum roller coaster height in feet
- `max_height_ft` (number): Filter by maximum roller coaster height in feet
- `min_speed_mph` (number): Filter by minimum roller coaster speed in mph
- `max_speed_mph` (number): Filter by maximum roller coaster speed in mph
- `min_inversions` (int): Filter by minimum number of inversions
- `max_inversions` (int): Filter by maximum number of inversions
- `has_inversions` (boolean): Filter rides with inversions (true) or without (false)
- `ordering` (string): Order results by field (name, -name, opening_date, -opening_date, average_rating, -average_rating, etc.)
- **Response Format**:
```typescript
{
strategy: 'client_side' | 'server_side',
data: RideData[],
total_count: number,
has_more: boolean,
filter_metadata: FilterMetadata
}
```
#### Progressive Loading
- **GET** `/api/v1/rides/hybrid/progressive/`
- **Description**: Load additional ride data for server-side filtering strategy
- **Query Parameters**: Same as main hybrid endpoint plus:
- `offset` (int, required): Number of records to skip for pagination
- **Usage**: Only use when main endpoint returns `strategy: 'server_side'` and `has_more: true`
#### Filter Metadata
- **GET** `/api/v1/rides/hybrid/filter-metadata/`
- **Description**: Get comprehensive filter metadata for dynamic filter generation
- **Returns**: Complete filter options including:
- Static options (categories, statuses, roller coaster types, track materials, launch types)
- Dynamic data (available parks, park areas, manufacturers, designers, ride models)
- Ranges (rating, height requirements, capacity, opening years, roller coaster stats)
- Boolean filters and ordering options
- **Caching**: Results cached for 5 minutes, automatically invalidated on data changes
#### Frontend Implementation Example
```typescript
// Basic hybrid filtering
const loadRides = async (filters = {}) => {
const params = new URLSearchParams();
// Add filters to params
Object.entries(filters).forEach(([key, value]) => {
if (value !== null && value !== undefined && value !== '') {
if (Array.isArray(value)) {
params.append(key, value.join(','));
} else {
params.append(key, value.toString());
}
}
});
const response = await fetch(`/api/v1/rides/hybrid/?${params}`, {
headers: { 'Authorization': `Bearer ${accessToken}` }
});
const data = await response.json();
if (data.strategy === 'client_side') {
// All data loaded - implement client-side filtering
return handleClientSideData(data);
} else {
// Server-side strategy - implement progressive loading
return handleServerSideData(data);
}
};
// Progressive loading for server-side strategy
const loadMoreRides = async (filters = {}, offset = 0) => {
const params = new URLSearchParams();
params.append('offset', offset.toString());
Object.entries(filters).forEach(([key, value]) => {
if (value !== null && value !== undefined && value !== '') {
if (Array.isArray(value)) {
params.append(key, value.join(','));
} else {
params.append(key, value.toString());
}
}
});
const response = await fetch(`/api/v1/rides/hybrid/progressive/?${params}`, {
headers: { 'Authorization': `Bearer ${accessToken}` }
});
return await response.json();
};
// Load filter metadata for dynamic filters
const loadFilterMetadata = async () => {
const response = await fetch('/api/v1/rides/hybrid/filter-metadata/');
return await response.json();
};
```
### Legacy Rides Listing
- **GET** `/api/v1/rides/`
- **Query Parameters**:
- `search`: Search in ride names and descriptions