optimize directory queries
[mygpo.git] / mygpo / directory / tags.py
blob6ba2d749f01b0d11ef0865358b4c098dd85ccadb
1 from collections import defaultdict, namedtuple
2 from operator import itemgetter
3 from datetime import datetime
4 from random import choice
5 from itertools import chain
7 from mygpo.core.models import Podcast
8 from mygpo.decorators import query_if_required
9 from mygpo.counter import Counter
10 from mygpo.core.proxy import proxy_object
11 from mygpo.directory.models import Category
12 from mygpo.db.couchdb.podcast import podcasts_for_tag
13 from mygpo.db.couchdb.directory import top_categories, category_for_tag
16 class Tag(object):
18 def __init__(self, tag):
19 self.tag = tag
22 def get_podcasts(self):
23 """ Returns the podcasts with the current tag.
25 Some podcasts might be returned twice """
27 return podcasts_for_tag(self.tag)
31 TagCloudEntry = namedtuple('TagCloudEntry', 'label weight')
34 class Topics(object):
36 def __init__(self, total=100, num_cat=10, podcasts_per_cat=10):
37 self.total = total
38 self.num_cat = num_cat
39 self.podcasts_per_cat = podcasts_per_cat
40 self._categories = None
41 self._tagcloud = None
44 def _needs_query(self):
45 return self._categories is None
48 def _query(self):
49 self._categories = top_categories(0, self.num_cat, True)
50 self._tagcloud = top_categories(self.num_cat, self.total-self.num_cat, False)
53 @property
54 @query_if_required()
55 def tagcloud(self):
56 self._tagcloud.sort(key = lambda x: x.label.lower())
57 return self._tagcloud
60 @query_if_required()
61 def max_weight(self):
62 return max([e.get_weight() for e in self.tagcloud] + [0])
64 @query_if_required()
65 def min_weight(self):
66 return min([e.get_weight() for e in self.tagcloud])
69 @property
70 @query_if_required()
71 def categories(self):
72 return self._categories
75 def _prepare_category(self, resp):
76 category = Category.wrap(resp['doc'])
77 category = proxy_object(category)
78 category.podcasts = category.get_podcasts(0, self.podcasts_per_cat)
79 return category
83 def update_category(podcast):
84 all_tags = list(chain.from_iterable(s for s in podcast.tags.values()))
86 random_tag = choice(all_tags)
88 category = category_for_tag(random_tag)
89 if not category:
90 category = Category(label=random_tag)
92 category.updated = datetime.utcnow()
94 category.podcasts = category.podcasts[:999]
96 # we don't need to CategoryEntry wrapper anymore
97 if any(isinstance(x, dict) for x in category.podcasts):
98 category.podcasts = filter(lambda x: isinstance(x, dict), category.podcasts)
99 category.podcasts = [e['podcast'] for e in category.podcasts]
101 if podcast.get_id() in category.podcasts:
102 category.podcasts.remove(podcast.get_id())
104 category.podcasts.insert(0, podcast.get_id())
105 category.save()