# Recommendations & Search Discovery is two systems working together: **recommendations** that surface products a shopper hasn't asked for, and **semantic search** that understands products a shopper *did* ask for — even when they spell it wrong. ## Recommendations `ProductRecommendationService` scores candidate products against a shopper's signals — primarily the categories and tags of items already in their wishlist — and returns a ranked list. It powers three surfaces: - **"You Might Also Like"** on the wishlist index — `Wishlist::SuggestedProductsComponent`. - **"Recommended for You"** on the homepage for signed-in shoppers with wishlist history — `Home::RecommendedProductsComponent`. - **"N people wishlisted this"** social proof on the product page — `Product::PopularityBadgeComponent`. Recommendation queries are constrained to the `Product.published` scope and the result set is **cached for 15 minutes**, so a hot homepage does not re-run the scoring query on every request. ## Semantic search A plain `LIKE '%term%'` query fails the moment a shopper types "runing shoes under 2000". `ProductSemanticSearchService` handles that class of query in three stages: 1. **Intent extraction** — parses constraints out of the raw query: price ceilings ("under 2000"), stock requirements ("in stock"), and similar modifiers, removing them from the text to be matched. 2. **Synonym expansion** — broadens the remaining terms so related words match. 3. **Trigram fallback** — when exact matching finds too little, PostgreSQL trigram similarity catches misspellings and near-misses ("runing" → "running"). The result is a search box that behaves the way shoppers expect it to, without a separate search cluster to operate. ## Why it lives in the monolith Both systems are plain PostgreSQL queries plus Ruby scoring — no Elasticsearch, no vector database, no ML service to deploy. For a catalog of this size that is the right trade: good-enough relevance, zero extra infrastructure, and logic that is trivial to test. ## Key files | Concern | Files | |---------|-------| | Services | `ProductRecommendationService`, `ProductSemanticSearchService`, `RecentlyViewedService` | | Components | `Wishlist::SuggestedProductsComponent`, `Home::RecommendedProductsComponent`, `Product::PopularityBadgeComponent` |