mirror of
https://github.com/discourse/discourse.git
synced 2025-03-14 10:33:43 +00:00
PERF: Optimize Category.subcategories
(#31802)
At the moment, every call to `Category.subcategories` causes an iteration through every single category. For sites with thousands of categories, this is incredibly expensive, and makes things like the category dropdown & sidebar rendering very slow. To improve things, we can create a map of parent_category => [child categories] in a single iteration, cache it, and then use that when finding subcategories. The `@computed` decorator ensures that this cache will be recalculated whenever the list of categories changes (e.g. when sideloading new categories in the experimental lazy-loaded-categories mode)
This commit is contained in:
@ -503,9 +503,9 @@ export default class Category extends RestModel {
|
||||
this.set("parent_category_id", newParentCategory?.id);
|
||||
}
|
||||
|
||||
@computed("site.categories.[]")
|
||||
@computed("site.categoriesByParentId")
|
||||
get subcategories() {
|
||||
return this.site.categories.filterBy("parent_category_id", this.id);
|
||||
return this.site.categoriesByParentId.get(this.id) || [];
|
||||
}
|
||||
|
||||
@computed("subcategories")
|
||||
|
@ -147,6 +147,17 @@ export default class Site extends RestModel {
|
||||
return map;
|
||||
}
|
||||
|
||||
@computed("categories.@each.parent_category_id")
|
||||
get categoriesByParentId() {
|
||||
const map = new Map();
|
||||
for (const category of this.categories) {
|
||||
const siblings = map.get(category.parent_category_id) || [];
|
||||
siblings.push(category);
|
||||
map.set(category.parent_category_id, siblings);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@discourseComputed("notification_types")
|
||||
notificationLookup(notificationTypes) {
|
||||
const result = [];
|
||||
|
Reference in New Issue
Block a user