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:
- 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.
- Synonym expansion — broadens the remaining terms so related words match.
- 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 |