Recommendation engines power personalized experiences. This guide covers collaborative and content-based filtering approaches.
Collaborative Filtering
User-Based Filtering
Find similar users and recommend their preferences:
typescript
export function findSimilarUsers(userId: string, ratings: Map<string, number[]>) {
const userRatings = ratings.get(userId)!;
const similarities = new Map<string, number>();
for (const [otherId, otherRatings] of ratings) {
if (otherId === userId) continue;
const similarity = cosineSimilarity(userRatings, otherRatings);
similarities.set(otherId, similarity);
}
return similarities;
}
function cosineSimilarity(a: number[], b: number[]): number {
const dotProduct = a.reduce((sum, val, i) => sum + val * b[i], 0);
const magnitudeA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
const magnitudeB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
return dotProduct / (magnitudeA * magnitudeB);
}Content-Based Filtering
Item Similarity
typescript
interface ItemFeatures {
category: string;
tags: string[];
price: number;
}
export function itemSimilarity(item1: ItemFeatures, item2: ItemFeatures): number {
let score = 0;
// Category match
if (item1.category === item2.category) score += 0.5;
// Tag overlap
const commonTags = item1.tags.filter(t => item2.tags.includes(t));
score += (commonTags.length / Math.max(item1.tags.length, item2.tags.length)) * 0.3;
// Price similarity
const priceDiff = Math.abs(item1.price - item2.price);
score += Math.max(0, 1 - priceDiff / 100) * 0.2;
return score;
}Hybrid Approach
Combine both methods:
typescript
export function getRecommendations(userId: string) {
const collaborative = getCollaborativeRecommendations(userId);
const contentBased = getContentBasedRecommendations(userId);
// Weighted combination
return collaborative
.map(item => ({ item, score: item.score * 0.6 }))
.concat(contentBased.map(item => ({ item, score: item.score * 0.4 })))
.sort((a, b) => b.score - a.score)
.slice(0, 10);
}Conclusion
Collaborative filtering works well with sufficient user data. Content-based filtering is better for cold starts. Combine both for optimal results.