improve / refactor feed-downloader
[mygpo.git] / mygpo / db / couchdb / directory.py
blobcfbf4726d72207a22e3a5b0feb4e6fee48f92e04
1 from collections import defaultdict, Counter
2 from operator import itemgetter
4 from mygpo.directory.models import Category
5 from mygpo.db.couchdb import get_main_database, get_categories_database, \
6 get_userdata_database
7 from mygpo.cache import cache_result
8 from mygpo.db.couchdb.utils import multi_request_view
9 from mygpo.db import QueryParameterMissing
12 def category_for_tag_uncached(tag):
14 if not tag:
15 raise QueryParameterMissing('tag')
17 db = get_categories_database()
18 r = db.view('categories/by_tags',
19 key = tag,
20 include_docs = True,
21 stale = 'update_after',
22 schema = Category
25 if r:
26 cat = r.first()
27 cat.set_db(db)
28 return cat
30 else:
31 return None
34 category_for_tag = cache_result(timeout=60*60)(category_for_tag_uncached)
37 @cache_result(timeout=60*60)
38 def top_categories(offset, count, with_podcasts=False):
40 if offset is None:
41 raise QueryParameterMissing('offset')
43 if not count:
44 raise QueryParameterMissing('count')
46 db = get_categories_database()
48 if with_podcasts:
49 r = db.view('categories/by_update',
50 descending = True,
51 skip = offset,
52 limit = count,
53 include_docs = True,
54 stale = 'update_after',
55 schema = Category,
58 else:
59 r = db.view('categories/by_update',
60 descending = True,
61 skip = offset,
62 limit = count,
63 stale = 'update_after',
64 wrapper = _category_wrapper,
67 categories = list(r)
69 for cat in categories:
70 cat.set_db(db)
72 return categories
75 def _category_wrapper(r):
76 c = Category()
77 c.label = r['value'][0]
78 c._weight = r['value'][1]
79 return c
82 def save_category(category):
83 db = get_categories_database()
84 db.save_doc(category)
87 def tags_for_podcast(podcast):
88 """ all tags for the podcast, in decreasing order of importance """
90 if not podcast:
91 raise QueryParameterMissing('podcast')
94 db = get_main_database()
95 res = db.view('tags/by_podcast',
96 startkey = [podcast.get_id(), None],
97 endkey = [podcast.get_id(), {}],
98 reduce = True,
99 group = True,
100 group_level = 2,
101 stale = 'update_after',
104 tags = Counter(dict((x['key'][1], x['value']) for x in res))
106 udb = get_userdata_database()
107 res = udb.view('usertags/by_podcast',
108 startkey = [podcast.get_id(), None],
109 endkey = [podcast.get_id(), {}],
110 reduce = True,
111 group = True,
112 group_level = 2,
115 tags.update(Counter(dict( (x['key'][1], x['value']) for x in res)))
117 get_tag = itemgetter(0)
118 return map(get_tag, tags.most_common())
121 def tags_for_user(user, podcast_id=None):
122 """ mapping of all podcasts tagged by the user with a list of tags """
124 if not user:
125 raise QueryParameterMissing('user')
128 udb = get_userdata_database()
129 res = udb.view('usertags/by_user',
130 startkey = [user._id, podcast_id],
131 endkey = [user._id, podcast_id or {}]
134 tags = defaultdict(list)
135 for r in res:
136 tags[r['key'][1]].append(r['value'])
137 return tags
140 def all_tags():
141 """ Returns all tags
143 Some tags might be returned twice """
144 db = get_main_database()
145 res = multi_request_view(db, 'podcasts/by_tag',
146 wrap = False,
147 reduce = True,
148 group = True,
149 group_level = 1
152 for r in res:
153 yield r['key'][0]
155 udb = get_userdata_database()
156 res = multi_request_view(udb, 'usertags/podcasts',
157 wrap = False,
158 reduce = True,
159 group = True,
160 group_level = 1
163 for r in res:
164 yield r['key'][0]
167 @cache_result(timeout=60*60)
168 def toplist(res_cls, view, key, limit, **view_args):
170 if not limit:
171 raise QueryParameterMissing('limit')
174 r = res_cls.view(view,
175 startkey = key + [{}],
176 endkey = key + [None],
177 include_docs = True,
178 descending = True,
179 limit = limit,
180 stale = 'update_after',
181 **view_args
183 return list(r)