The problem
An online marketplace's search function returned zero results for 92% of queries. Users searching for "mens shoes" found nothing, despite having 3,400 men's shoe listings. Support tickets complained: "Search is broken", "Can't find anything", "Is this site empty?". Analytics showed users performed an average of 4.7 failed searches before giving up. The company was losing $85,000/week in missed sales.
How AI created this issue
The developer asked Claude to implement a product search feature. Claude created a basic exact-match SQL query:
# Claude's search implementation
def search_products(query):
# Simple exact match search
sql = """
SELECT * FROM products
WHERE LOWER(name) = LOWER(%s)
OR LOWER(description) = LOWER(%s)
ORDER BY created_at DESC
"""
results = db.execute(sql, [query, query])
return results
# This returns nothing for "mens shoes" because products are named:
# - "Men's Running Shoes - Nike Air Max"
# - "Casual Leather Shoes for Men"
# - "Mens Athletic Footwear"
Claude's search required exact matches of the entire field. It didn't handle plurals, typos, word order, or partial matches. The AI never suggested full-text search, fuzzy matching, or relevance scoring - just a basic string comparison that worked in the trivial example but failed with real user queries.
The solution
- PostgreSQL full-text search implementation: Replaced exact match with intelligent search:
# Proper search with PostgreSQL full-text search def search_products(query): # Create search vector from multiple fields sql = """ WITH search_query AS ( SELECT plainto_tsquery('english', %s) AS query ) SELECT p.*, ts_rank(search_vector, query) AS rank, ts_headline('english', name, query, 'StartSel=, StopSel=') AS highlighted_name FROM products p, search_query WHERE search_vector @@ query OR name ILIKE '%%' || %s || '%%' -- Fallback partial match ORDER BY CASE WHEN name ILIKE %s || '%%' THEN 0 ELSE 1 END, -- Prioritize prefix matches rank DESC, popularity DESC LIMIT 50 """ # Handle common variations normalized_query = query.replace("mens", "men's").replace("shoes", "shoe") return db.execute(sql, [normalized_query, query, query])
- Search index optimization: Added GIN indexes and search vectors:
-- Add search vector column ALTER TABLE products ADD COLUMN search_vector tsvector; -- Populate with weighted fields UPDATE products SET search_vector = setweight(to_tsvector('english', coalesce(name, '')), 'A') || setweight(to_tsvector('english', coalesce(brand, '')), 'B') || setweight(to_tsvector('english', coalesce(category, '')), 'C') || setweight(to_tsvector('english', coalesce(description, '')), 'D'); -- Create GIN index for fast searches CREATE INDEX idx_products_search ON products USING GIN (search_vector); -- Auto-update trigger CREATE TRIGGER update_search_vector BEFORE INSERT OR UPDATE ON products FOR EACH ROW EXECUTE FUNCTION tsvector_update_trigger(search_vector, 'pg_catalog.english', name, brand, category, description);
- Typo tolerance: Implemented trigram similarity for fuzzy matching
- Synonym handling: Added common product synonyms (shoe/footwear, men's/mens)
- Search analytics: Track failed searches to continuously improve
The results
- Search success rate jumped from 8% to 94%
- Average searches per session: 4.7 → 1.3
- Conversion rate increased 287% as users found products
- Support tickets about search dropped 96%
- Revenue increased $340,000/month from improved discovery
- Search response time: 1.2s → 85ms with proper indexing
The team learned that AI tools often implement the simplest possible solution that technically works. Real-world search requires understanding of linguistics, user behavior, and database capabilities. They now start with proven search solutions (Elasticsearch, PostgreSQL FTS) rather than asking AI to reinvent search from scratch.
Ready to fix your codebase?
Let us analyze your application and resolve these issues before they impact your users.
Get Diagnostic Assessment →