Skip to content

Commit

Permalink
Calculate recommended items without scanning the entire database by
Browse files Browse the repository at this point in the history
using pre-rated items and comparing against similar items that have
already been stored
  • Loading branch information
coleifer committed May 27, 2010
1 parent 7d0c63e commit 044a4bd
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
7 changes: 6 additions & 1 deletion ratings/tests/tests.py
Expand Up @@ -3,7 +3,7 @@

from ratings.models import RatedItem
from ratings.tests.models import Food, Beverage, BeverageRating
from ratings.utils import sim_euclidean_distance, sim_pearson_correlation, top_matches, recommendations, calculate_similar_items
from ratings.utils import sim_euclidean_distance, sim_pearson_correlation, top_matches, recommendations, calculate_similar_items, recommended_items


class BaseRatingsTestCase(TestCase):
Expand Down Expand Up @@ -351,3 +351,8 @@ def test_similar_items(self):

other_for_food_a = self.food_a.ratings.similar_items()[0]
self.assertEqual(top_for_food_a, other_for_food_a)

def test_recommended_items(self):
calculate_similar_items(RatedItem.objects.all())
result = recommended_items(RatedItem.objects.all(), self.user_g)
self.assertEqual(str(result), '[(3.6100310668021822, <Food: food_a>), (3.5313950341859761, <Food: food_f>), (2.9609998607242685, <Food: food_c>)]')
28 changes: 28 additions & 0 deletions ratings/utils.py
Expand Up @@ -211,3 +211,31 @@ def _store_top_matches(ratings_queryset, rated_queryset, num, is_gfk):
if created or si.score != score:
si.score = score
si.save()

def recommended_items(ratings_queryset, user):
from ratings.models import SimilarItem
scores = {}
total_sim = {}

for item in ratings_queryset.filter(user=user):

for similar_item in SimilarItem.objects.get_for_item(item.content_object):

actual = similar_item.similar_object
lookup_kwargs = ratings_queryset.model.lookup_kwargs(actual)
lookup_kwargs['user'] = user

if ratings_queryset.filter(**lookup_kwargs):
continue

scores.setdefault(actual, 0)
scores[actual] += similar_item.score * item.score

total_sim.setdefault(actual, 0)
total_sim[actual] += similar_item.score

rankings = [(score/total_sim[item], item) for item, score in scores.iteritems()]

rankings.sort()
rankings.reverse()
return rankings

0 comments on commit 044a4bd

Please sign in to comment.