{"openapi":"3.0.3","info":{"title":"Search & Recommendation Engine API","description":"⚡ Ultra-fast restaurant search and AI-powered recommendation engine","version":"2.0.0"},"tags":[{"name":"recommendations","description":"🎯 AI-powered restaurant recommendations"},{"name":"search","description":"🔍 Advanced restaurant search"},{"name":"analytics","description":"📊 Search & recommendation analytics"}],"paths":{"/recommendations/":{"get":{"parameters":[{"schema":{"type":"string"},"in":"query","name":"q","required":false},{"schema":{"type":"string"},"in":"query","name":"city","required":false},{"schema":{"type":"string"},"in":"query","name":"userId","required":false},{"schema":{"type":"string"},"in":"query","name":"lat","required":false},{"schema":{"type":"string"},"in":"query","name":"lng","required":false},{"schema":{"type":"string"},"in":"query","name":"radius","required":false},{"schema":{"type":"string"},"in":"query","name":"cuisines","required":false},{"schema":{"type":"string"},"in":"query","name":"priceLevel","required":false},{"schema":{"type":"string"},"in":"query","name":"features","required":false},{"schema":{"type":"string"},"in":"query","name":"tags","required":false},{"schema":{"type":"string"},"in":"query","name":"useBayesian","required":false},{"schema":{"anyOf":[{"const":"breakfast","type":"string"},{"const":"lunch","type":"string"},{"const":"dinner","type":"string"},{"const":"late_night","type":"string"},{"const":"date_night","type":"string"},{"const":"family","type":"string"},{"const":"business","type":"string"}]},"in":"query","name":"context","required":false},{"schema":{"type":"string"},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"openNow","required":false},{"schema":{"type":"string"},"in":"query","name":"timezoneOffset","required":false},{"schema":{"type":"string"},"in":"query","name":"mealType","required":false},{"schema":{"type":"string"},"in":"query","name":"offset","required":false},{"schema":{"type":"string"},"in":"query","name":"page","required":false},{"schema":{"type":"string"},"in":"query","name":"dietaryRestrictions","required":false},{"schema":{"type":"string"},"in":"query","name":"minRating","required":false}],"operationId":"getRecommendations","tags":["recommendations"],"summary":"🚀 Unified Restaurant Search - One Endpoint for Everything!","description":"\n**The ultimate restaurant search endpoint** that handles natural language queries, structured filters, and everything in between.\n\n**🎯 How it works:**\n- **Natural Language**: Just type what you want like \"italian restaurants\" or \"best pizza near me\"\n- **Structured Filters**: Use specific parameters for precise control\n- **Smart Parsing**: Automatically understands your intent and applies the best strategy\n- **Proper Sorting**: Results are intelligently ranked by relevance, rating, and distance\n\n**🔍 Natural Language Examples:**\n- `?q=italian restaurants` → Finds Italian restaurants\n- `?q=best pizza near me` → Finds top-rated pizza places nearby\n- `?q=romantic dinner spots` → Finds romantic restaurants\n- `?q=cheap sushi with delivery` → Finds affordable sushi with delivery\n\n**📍 Location Parameters:**\n- `lat/lng`: Your coordinates (decimal degrees)\n- `radius`: Search radius in meters (default: 5000, max: 50000)\n\n**🍽️ Preference Parameters:**\n- `cuisines`: italian,chinese,mexican,indian,thai,french,american\n- `priceLevel`: 1=$ (budget), 2=$$ (moderate), 3=$$$ (expensive), 4=$$$$ (luxury)\n- `features`: wifi,parking,delivery,takeout,reservations,outdoor,halal,vegan\n- `tags`: romantic,family-friendly,business,casual,fine-dining,popular\n\n**🎭 Context Parameters:**\n- `breakfast`: Morning dining (6-11 AM optimized)\n- `lunch`: Midday meals (11 AM-3 PM optimized)  \n- `dinner`: Evening dining (5-10 PM optimized)\n- `late_night`: Late hours (10 PM+ optimized)\n- `date_night`: Romantic atmosphere, upscale\n- `family`: Kid-friendly, spacious, parking\n- `business`: Quiet, wifi, professional atmosphere\n\n**🧮 Advanced Features:**\n- `useBayesian=true`: Enable probabilistic modeling for better accuracy\n- `userId`: Enable personalized recommendations (header: x-user-id)\n\n**⚡ Performance:**\n- **< 50ms**: Hot cache hits\n- **< 150ms**: Cold cache with database query\n- **< 500ms**: Complex multi-strategy analysis\n- **Redis caching**: 5-30 minute TTL based on data type\n\n**🎯 Smart Strategy Selection:**\n- Natural language queries → NLP parsing + content-based\n- Location + preferences → Hybrid approach\n- Location only → Location-popular\n- User ID + preferences → Collaborative filtering\n- Context only → Context-aware\n- Default → Popular restaurants\n\n**📊 Response Format:**\n- `restaurants`: Array of restaurants with proper sorting\n- `strategy`: Which strategy was used\n- `executionTime`: Response time in milliseconds\n- `fromCache`: Whether result came from cache\n- `totalResults`: Total number of matching restaurants\n- `query`: Parsed query information (for natural language queries)\n        ","examples":{"Natural Language":{"description":"Search using natural language","value":{"q":"italian restaurants"}},"Location Based":{"description":"Find restaurants near a location","value":{"lat":"25.2048","lng":"55.2708","radius":"3000"}},"Cuisine Specific":{"description":"Find specific cuisine with location","value":{"q":"chinese food","lat":"25.2048","lng":"55.2708"}},"Advanced Filters":{"description":"Complex search with multiple filters","value":{"q":"romantic dinner","lat":"25.2048","lng":"55.2708","priceLevel":"3,4","features":"parking,reservations"}}},"responses":{"200":{}}}},"/gp":{"get":{"parameters":[{"description":"Text query for Google Places search (e.g., 'italian restaurants', 'pizza near me')","schema":{"type":"string"},"in":"query","name":"q","required":true},{"description":"Latitude for location bias","schema":{"type":"string"},"in":"query","name":"lat","required":false},{"description":"Longitude for location bias","schema":{"type":"string"},"in":"query","name":"lng","required":false},{"description":"City hint to improve location relevance (e.g., 'Dubai', 'Berlin')","schema":{"type":"string"},"in":"query","name":"city","required":false},{"description":"Search radius in meters (default: 5000, max: 50000)","schema":{"type":"string"},"in":"query","name":"radius","required":false},{"description":"Comma-separated cuisines (e.g., 'indian,italian')","schema":{"type":"string"},"in":"query","name":"cuisines","required":false},{"description":"Comma-separated tags/features (e.g., 'serves_great_coffee,romantic')","schema":{"type":"string"},"in":"query","name":"tags","required":false},{"description":"Comma-separated price levels: 1=$ (budget), 2=$$ (moderate), 3=$$$ (expensive), 4=$$$$ (luxury)","schema":{"type":"string"},"in":"query","name":"priceLevel","required":false},{"description":"Minimum rating (0-5)","schema":{"type":"string"},"in":"query","name":"minRating","required":false},{"description":"Filter for restaurants open now (true/false)","schema":{"type":"string"},"in":"query","name":"openNow","required":false},{"description":"Language code for results (default: 'en')","schema":{"type":"string"},"in":"query","name":"languageCode","required":false},{"description":"Rank results by distance (requires lat/lng parameters)","schema":{"type":"string","const":"DISTANCE"},"in":"query","name":"rankPreference","required":false},{"description":"Maximum number of results (default: 20, max: 60)","schema":{"type":"string"},"in":"query","name":"limit","required":false},{"description":"Offset for pagination","schema":{"type":"string"},"in":"query","name":"offset","required":false},{"description":"Page number for pagination","schema":{"type":"string"},"in":"query","name":"page","required":false},{"description":"Comma-separated boundary filters: 'within', 'expanded', 'outside'. Default: 'within,expanded' (excludes 'outside')","schema":{"type":"string"},"in":"query","name":"boundary","required":false}],"operationId":"getGp","tags":["search"],"summary":"🌐 Google Places Text Search","description":"\n**Search restaurants using Google Places Text Search API (New)**\n\nThis endpoint uses Google Places API to find restaurants based on text queries and returns results in a format similar to the recommendations endpoint.\n\n**🔍 Query Examples:**\n- `?q=italian restaurants` → Finds Italian restaurants\n- `?q=pizza near me` → Finds pizza places\n- `?q=romantic dinner spots` → Finds romantic restaurants\n- `?q=spicy vegetarian food in Sydney, Australia` → Finds specific restaurants in a location\n\n**📍 Location Parameters:**\n- `lat/lng`: Your coordinates (decimal degrees) for location bias\n- `radius`: Search radius in meters (default: 5000, max: 50000)\n\n**💰 Price Filter:**\n- `priceLevel`: 1=$ (budget), 2=$$ (moderate), 3=$$$ (expensive), 4=$$$$ (luxury)\n- Can be comma-separated: `priceLevel=1,2`\n\n**⭐ Rating Filter:**\n- `minRating`: Minimum rating from 0 to 5\n\n**🕐 Open Now Filter:**\n- `openNow=true`: Only return restaurants that are currently open\n\n**🔤 Language:**\n- `languageCode`: Language for results (e.g., 'en', 'es', 'fr')\n- Default: 'en'\n\n**📊 Ranking:**\n- `rankPreference=DISTANCE`: Sort by distance (requires lat/lng parameters)\n- Default: Relevance-based ranking\n\n**📄 Pagination:**\n- `limit`: Maximum results per page (default: 20, max: 60)\n- `offset`: Skip N results\n- `page`: Page number (alternative to offset)\n\n**📊 Response Format:**\n- `restaurants`: Array of restaurants matching the query\n- `strategy`: Always \"google_places\"\n- `executionTime`: Response time in milliseconds\n- `fromCache`: Always false (Google Places API doesn't support caching)\n- `totalResults`: Total number of matching restaurants\n- `pagination`: Pagination metadata\n- `query`: Parsed query information\n- `performance`: Performance metrics\n\n**⚡ Performance:**\n- Results are fetched directly from Google Places API\n- Response time typically 200-500ms depending on network and query complexity\n\n**🎯 Use Cases:**\n- Real-time restaurant discovery\n- Finding restaurants by name or description\n- Location-based searches with Google's comprehensive database\n- Getting up-to-date restaurant information\n        ","examples":{"Simple Text Search":{"description":"Search using text query","value":{"q":"italian restaurants"}},"Location-Based Search":{"description":"Find restaurants near a location","value":{"q":"pizza","lat":"25.2048","lng":"55.2708","radius":"3000"}},"With Filters":{"description":"Search with price and rating filters","value":{"q":"romantic dinner","lat":"25.2048","lng":"55.2708","priceLevel":"3,4","minRating":"4.0","openNow":"true"}},"Distance Ranking":{"description":"Sort results by distance","value":{"q":"chinese food","lat":"25.2048","lng":"55.2708","rankPreference":"DISTANCE"}}},"responses":{"200":{}}}},"/admin/rebuild-index":{"post":{"operationId":"postAdminRebuild-index","tags":["admin"],"summary":"🔄 Rebuild Search Index","description":"\n**Manually rebuild the entire search index from the database in the background.**\n\nThis operation:\n- Runs in the background to avoid HTTP timeouts\n- Fetches all restaurants from the database\n- SQL-based search is always up-to-date (no index rebuild needed)\n- Caches the new index in Redis\n- Returns immediately with an operation ID to track progress\n\n**Response includes:**\n- `operationId`: Unique ID to track the operation\n- `statusUrl`: URL to check operation status\n\n**When to use:**\n- After bulk restaurant data imports\n- When search results seem outdated\n- After database schema changes affecting restaurant data\n- When the cached index is corrupted\n\n**Usage:**\n1. Call this endpoint to start rebuild\n2. Use the returned `statusUrl` to check progress\n3. Operation completes when status becomes \"completed\"\n        ","responses":{"200":{}}}},"/admin/operation-status/{operationId}":{"get":{"parameters":[{"schema":{"type":"string"},"in":"path","name":"operationId","required":true}],"operationId":"getAdminOperation-statusByOperationId","tags":["admin"],"summary":"📊 Get Operation Status","description":"\n**Check the status of a background operation.**\n\nReturns detailed information about:\n- Operation type (rebuild, update)\n- Current status (running, completed, failed)\n- Progress message\n- Start/end times\n- Duration\n- Error details (if failed)\n\n**Status Values:**\n- `running`: Operation is in progress\n- `completed`: Operation finished successfully\n- `failed`: Operation encountered an error\n        ","responses":{"200":{}}}},"/admin/operations":{"get":{"operationId":"getAdminOperations","tags":["admin"],"summary":"📋 List All Operations","description":"\n**Get a list of all background operations.**\n\nReturns all operations (recent first) with their status and details.\nUseful for monitoring and debugging background processes.\n        ","responses":{"200":{}}}},"/admin/clear-cache":{"post":{"operationId":"postAdminClear-cache","tags":["admin"],"summary":"🧹 Clear Search Cache","description":"\n**Comprehensively clear ALL search-related caches.**\n\nThis operation clears:\n- 🔍 Search index cache (removed - using SQL-based search)\n- 📊 Search result caches (rec:v3:*)\n- 💡 Search suggestion caches (suggestions:*)\n- 🚀 Advanced search caches (adv_search:*)\n- 🧠 Bayesian inference caches (bayesian:*)\n- 👤 User preference caches (user_posterior:*)\n- 🏪 Restaurant-related caches (restaurant:*)\n- 📍 Location caches (location_cache:*)\n- 🍽️ Cuisine caches (cuisine_cache:*)\n- 🤖 NLP processing caches (nlp_cache:*)\n- 📈 Scoring caches (scoring_cache:*)\n- 🔄 Any other search/recommendation caches\n\n**Advanced Features:**\n- Pattern-based deletion for comprehensive cleanup\n- Multiple Redis SCAN operations to find missed keys\n- Scans for: *search*, *rec*, *user* patterns\n- Error handling for individual pattern failures\n- Detailed logging of cleared cache counts\n\n**When to use:**\n- When you want to force completely fresh search results\n- After updating restaurant data or search algorithms\n- When troubleshooting cache-related issues\n- Before rebuilding the search index\n- When switching between different search strategies\n- After user preference model updates\n        ","responses":{"200":{}}}},"/admin/index-stats":{"get":{"operationId":"getAdminIndex-stats","tags":["admin"],"summary":"📊 Get Search Index Statistics","description":"\n**Get detailed statistics about the search index.**\n\nReturns information about:\n- Index size and document count\n- Last update timestamp\n- Index readiness status\n- Cache status and TTL\n        ","responses":{"200":{}}}},"/admin/update-index":{"post":{"parameters":[],"operationId":"postAdminUpdate-index","tags":["admin"],"summary":"🔄 Update Index for Specific Restaurants","description":"\n**Update the search index for specific restaurants in the background.**\n\nThis is more efficient than rebuilding the entire index when you only need to update a few restaurants.\nRuns in the background to avoid HTTP timeouts.\n\n**Request Body:**\n```json\n{\n  \"restaurantIds\": [\"rest1\", \"rest2\", \"rest3\"]\n}\n```\n\n**Response includes:**\n- `operationId`: Unique ID to track the operation\n- `statusUrl`: URL to check operation status\n- `restaurantCount`: Number of restaurants being updated\n\n**When to use:**\n- After updating specific restaurant data\n- When adding new restaurants\n- For incremental index updates\n\n**Usage:**\n1. Call this endpoint with restaurant IDs\n2. Use the returned `statusUrl` to check progress\n3. Operation completes when status becomes \"completed\"\n        ","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"restaurantIds":{"type":"array","items":{"type":"string"}}},"required":["restaurantIds"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"restaurantIds":{"type":"array","items":{"type":"string"}}},"required":["restaurantIds"]}},"text/plain":{"schema":{"type":"object","properties":{"restaurantIds":{"type":"array","items":{"type":"string"}}},"required":["restaurantIds"]}}}},"responses":{"200":{}}}},"/":{"get":{"operationId":"getIndex","responses":{"200":{}}}},"/health":{"get":{"operationId":"getHealth","responses":{"200":{}}}}},"components":{"schemas":{}}}