Skip to content

fix(BUY-62409): boost laptop relevance 2x, demote accessories in FTS ranking#222

Open
BuyWhere wants to merge 6 commits into
mainfrom
fix/BUY-62409-laptop-relevance-boost
Open

fix(BUY-62409): boost laptop relevance 2x, demote accessories in FTS ranking#222
BuyWhere wants to merge 6 commits into
mainfrom
fix/BUY-62409-laptop-relevance-boost

Conversation

@BuyWhere

Copy link
Copy Markdown
Owner

Problem

QA re-verification of BUY-62409 (2026-07-14T18:13Z) confirmed country inference works correctly (country=sg), but search results for 'laptop singapore' are still broken: top 20 results are 100% laptop accessories (Targus Slipskin sleeves, Nano Lock cable locks, Spigen laptop bags, etc.) — zero actual laptop computers.

Root Cause

PostgreSQL's ts_rank() text search ranks products purely by text similarity. For queries containing 'laptop', accessories like 'Laptop Sleeve', 'Laptop Stand', 'Laptop Case', 'Laptop Bag', 'Laptop Cooling Pad', 'Laptop Charger' etc. score as highly relevant because they mention 'laptop' in their title. The search has no semantic understanding that 'laptop' as a standalone device is different from 'laptop accessory'.

Fix

Applied a 2x relevance boost to products whose titles contain 'laptop' but do NOT contain accessory keywords:

  • sleeve
  • case, bag, stand, pad
  • cooler, adapter
  • dock, hub, lock, briefcase
  • charger, table

This demotes laptop accessories relative to actual laptop computers in the FTS ranking, on both query paths (small result set <1000 rows and large result sets with candidate LIMIT).

Changes

  • api/src/routes/products.ts: Modified ORDER BY for both FTS ranking paths to multiply ts_rank by the CASE expression

Oracle (CDO) and others added 6 commits July 7, 2026 04:19
…not touched

- Add inferCountryFromQuery() function to detect 'singapore'/'sg' → 'sg' and 'us'/'usa'/'united states'/'america' → 'us'
- Add countryTouched flag to track if user manually changed country dropdown
- Only use query inference when country selector was never touched; otherwise respect user's manual selection
- Fixes issue where 'laptop singapore' was defaulting to US instead of inferring Singapore market

# Conflicts:
#	src/components/HomeProductSearch.tsx
…(BUY-59843)

- priceRefresh now sets products.updated_at = NOW() so /v1/products/search
  returns fresh timestamps after the nightly pulse
- New scraper_scheduler.py daemon runs existing scrapers on schedule,
  pushing data through the ingest API which sets updated_at = NOW()
- Deploy docs and systemd unit files for the scraper scheduler
… is unavailable

- getSeoLandingProducts returns [] instead of fallbackProducts on API failure
- SeoLandingPage conditionally renders product grid and comparison table only
  when live data is available
- Hero badge 'Live BuyWhere search results' hidden when no live products
- Graceful search CTA shown when catalog snapshot cannot be populated
- Removed fallbackProducts field from SeoLandingPageConfig and all page configs

Fixes BUY-62408
- Add isPlaceholderProduct() to detect generic Product A/Brand A patterns
- Add buildComparisonFromProducts() to build table from real API data
- getSeoLandingProducts() returns [] on failure instead of fallbackProducts
- Remove fallbackProducts config entries
- SeoLandingPage: gate product grid, comparison table, and 'Live' badge on real product counts
- Graceful search CTA fallback when no live products available
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant