From 9dffd17bd597b2b20c93a03efe79720fc9d07c65 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 6 Oct 2015 10:29:30 +0200 Subject: [PATCH] [IMP] website_forum: users page performances The read_group collating user badge counts is extremely slow when there's a large number of users (possibly even slower than 8.0's naive approach), replace the whole thing by a single SQL query seems to yield pretty significant (~2 orders of magnitude) performance improvements on the computing function resulting in ~1 order of magnitude improvement for the page as a whole. --- addons/website_forum/models/res_users.py | 28 ++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/addons/website_forum/models/res_users.py b/addons/website_forum/models/res_users.py index 2f437affbb0..44206d2b27e 100644 --- a/addons/website_forum/models/res_users.py +++ b/addons/website_forum/models/res_users.py @@ -30,18 +30,24 @@ class Users(models.Model): def _get_user_badge_level(self): """ Return total badge per level of users TDE CLEANME: shouldn't check type is forum ? """ - badge_groups = self.env['gamification.badge.user'].read_group( - [('level', 'in', ['gold', 'silver', 'bronze'])], - ['user_id', 'level', 'badge_id'], - ['user_id', 'level'], - lazy=False) - badge_data = dict() - for group in badge_groups: - badge_data.setdefault(group['user_id'][0], dict())[group['level']] = group['__count'] for user in self: - user.gold_badge = badge_data.get(user.id) and badge_data[user.id].get('gold', 0) or 0 - user.silver_badge = badge_data.get(user.id) and badge_data[user.id].get('silver', 0) or 0 - user.bronze_badge = badge_data.get(user.id) and badge_data[user.id].get('bronze', 0) or 0 + user.gold_badge = 0 + user.silver_badge = 0 + user.bronze_badge = 0 + + self.env.cr.execute(""" + SELECT bu.user_id, b.level, count(1) + FROM gamification_badge_user bu, gamification_badge b + WHERE bu.user_id IN %s + AND bu.badge_id = b.id + AND b.level IS NOT NULL + GROUP BY bu.user_id, b.level + ORDER BY bu.user_id; + """, [tuple(self.ids)]) + + for (user_id, level, count) in self.env.cr.fetchall(): + # levels are gold, silver, bronze but fields have _badge postfix + self.browse(user_id)['{}_badge'.format(level)] = count @api.model def _generate_forum_token(self, user_id, email):