mirror of
https://github.com/discourse/discourse.git
synced 2024-11-30 08:43:45 +08:00
PERF: improve category moderators query (#12538)
In the about page, we list a certain number of category moderators. This rewrites the SQL query used to retrieve the most recent category moderators in order to perform better with a large number of users/categories/category moderators. TIL: you can ORDER BY inside an ARRAY_AGG in postgres TIL: you can slide ARRAYS in postgres
This commit is contained in:
parent
db7be947df
commit
e8cad4bbf3
|
@ -83,32 +83,28 @@ class About
|
||||||
def category_moderators
|
def category_moderators
|
||||||
allowed_cats = Guardian.new(@user).allowed_category_ids
|
allowed_cats = Guardian.new(@user).allowed_category_ids
|
||||||
return [] if allowed_cats.blank?
|
return [] if allowed_cats.blank?
|
||||||
|
|
||||||
cats_with_mods = Category.where.not(reviewable_by_group_id: nil).pluck(:id)
|
cats_with_mods = Category.where.not(reviewable_by_group_id: nil).pluck(:id)
|
||||||
|
|
||||||
category_ids = cats_with_mods & allowed_cats
|
category_ids = cats_with_mods & allowed_cats
|
||||||
return [] if category_ids.blank?
|
return [] if category_ids.blank?
|
||||||
|
|
||||||
per_cat_limit = category_mods_limit / category_ids.size
|
per_cat_limit = category_mods_limit / category_ids.size
|
||||||
per_cat_limit = 1 if per_cat_limit < 1
|
per_cat_limit = 1 if per_cat_limit < 1
|
||||||
results = DB.query(<<~SQL, category_ids: category_ids, per_cat_limit: per_cat_limit)
|
|
||||||
SELECT c.id category_id, user_ids
|
results = DB.query(<<~SQL, category_ids: category_ids)
|
||||||
FROM categories c
|
SELECT c.id category_id
|
||||||
CROSS JOIN LATERAL (
|
, (ARRAY_AGG(u.id ORDER BY u.last_seen_at DESC))[:#{per_cat_limit}] user_ids
|
||||||
SELECT ARRAY(
|
FROM categories c
|
||||||
SELECT u.id
|
JOIN group_users gu ON gu.group_id = c.reviewable_by_group_id
|
||||||
FROM users u
|
JOIN users u ON u.id = gu.user_id
|
||||||
JOIN group_users gu
|
WHERE c.id IN (:category_ids)
|
||||||
ON gu.group_id = c.reviewable_by_group_id AND gu.user_id = u.id
|
GROUP BY c.id
|
||||||
ORDER BY last_seen_at DESC
|
ORDER BY c.position
|
||||||
LIMIT :per_cat_limit
|
|
||||||
) AS user_ids
|
|
||||||
) user_ids
|
|
||||||
WHERE c.id IN (:category_ids)
|
|
||||||
SQL
|
SQL
|
||||||
moderators = {}
|
|
||||||
User.where(id: results.map(&:user_ids).flatten.uniq).each do |user|
|
moderators = User.where(id: results.map(&:user_ids).flatten.uniq).map { |u| [u.id, u] }.to_h
|
||||||
moderators[user.id] = user
|
|
||||||
end
|
|
||||||
moderators
|
|
||||||
results.map do |row|
|
results.map do |row|
|
||||||
CategoryMods.new(row.category_id, row.user_ids.map { |id| moderators[id] })
|
CategoryMods.new(row.category_id, row.user_ids.map { |id| moderators[id] })
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user