PERF: Use DB for topic enumeration tasks (#7)

Use SQL statements versus loading topics into memory to allow handling of large datasets.
This commit is contained in:
Justin DiRose 2020-06-16 13:20:08 -05:00 committed by GitHub
parent 6eb3c7574d
commit 90f8bdf945
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 38 deletions

View File

@ -58,10 +58,7 @@ export default Ember.Controller.extend({
@discourseComputed("loadMoreUrl")
canLoadMore(loadMoreUrl) {
if (loadMoreUrl === null || this.isLoadingMore) {
return false;
}
return true;
return loadMoreUrl === null ? false : true;
},
@discourseComputed("searchTerm")
@ -69,9 +66,9 @@ export default Ember.Controller.extend({
return !!searchTerm;
},
@discourseComputed("isSearching", "topics")
searchCount(isSearching, topics) {
if (isSearching) return topics.length;
@discourseComputed("isSearching", "model")
searchCount(isSearching, model) {
if (isSearching) return model.search_count;
},
emptySearchResults: Ember.computed.equal("searchCount", 0),
@ -182,7 +179,7 @@ export default Ember.Controller.extend({
},
loadMore() {
if (this.canLoadMore) {
if (this.canLoadMore && !this.isLoadingMore) {
this.set("isLoadingMore", true);
KnowledgeExplorer.loadMore(this.loadMoreUrl).then(result => {

View File

@ -42,7 +42,19 @@ export default {
},
loadMore(loadMoreUrl) {
return ajax(loadMoreUrl);
let promise = ajax(loadMoreUrl);
promise = promise.then(data => {
data.topics.topic_list.topics = data.topics.topic_list.topics.map(
topic => {
topic = Topic.create(topic);
return topic;
}
);
return data;
});
return promise;
},
getTopic

View File

@ -72,6 +72,7 @@ module KnowledgeExplorer
pd.search_data @@ #{escaped_ts_query}
)
SQL
search_count = results.count
end
if @filters[:order] == "title"
@ -88,8 +89,15 @@ module KnowledgeExplorer
end
end
tags = tag_count(results)
categories = categories_count(results)
# conduct a second set of joins so we don't mess up the count
count_query = results.joins <<~SQL
INNER JOIN topic_tags tt2 ON tt2.topic_id = topics.id
INNER JOIN tags t2 ON t2.id = tt2.tag_id
SQL
tags = count_query.group('t2.name').count
tags = create_tags_object(tags)
categories = results.where('topics.category_id IS NOT NULL').group('topics.category_id').count
categories = create_categories_object(categories)
results_length = results.length
@ -103,7 +111,7 @@ module KnowledgeExplorer
end_of_list = true if results_length < @limit
end
results = results[offset...page_range]
results = results.offset(offset).limit(@limit) #results[offset...page_range]
# assemble the object
topic_query = tq.create_list(:knowledge_explorer, { unordered: true }, results)
@ -116,45 +124,33 @@ module KnowledgeExplorer
topic_list['load_more_url'] = nil
end
{ tags: tags, categories: categories, topics: topic_list }
{ tags: tags, categories: categories, topics: topic_list, search_count: search_count }
end
def tag_count(results)
tags = []
def create_tags_object(tags)
tags_object = []
results.each do |topic|
topic.tags.each do |tag|
active = @filters[:tags].include?(tag.name) if @filters[:tags]
if tags.none? { |item| item[:id].to_s == tag.name }
tags << { id: tag.name, count: 1, active: active || false }
else
tag_index = tags.index(tags.find { |item| item[:id].to_s == tag.name })
tags[tag_index][:count] += 1
end
end
tags.each do |tag|
active = @filters[:tags].include?(tag[0]) if @filters[:tags]
tags_object << { id: tag[0], count: tag[1], active: active || false }
end
allowed_tags = DiscourseTagging.filter_allowed_tags(Guardian.new(@user)).map(&:name)
tags = tags.select { |tag| allowed_tags.include?(tag[:id]) }
tags_object = tags_object.select { |tag| allowed_tags.include?(tag[:id]) }
tags.sort_by { |tag| [tag[:active] ? 0 : 1, -tag[:count]] }
tags_object.sort_by { |tag| [tag[:active] ? 0 : 1, -tag[:count]] }
end
def categories_count(results)
categories = []
def create_categories_object(categories)
categories_object = []
results.each do |topic|
active = @filters[:category].include?(topic.category_id.to_s) if @filters[:category]
if categories.none? { |item| item[:id] == topic.category_id }
categories << { id: topic.category_id, count: 1, active: active || false }
else
category_index = categories.index(categories.find { |item| item[:id] == topic.category_id })
categories[category_index][:count] += 1
end
categories.each do |category|
active = @filters[:category].include?(category[0].to_s) if @filters[:category]
categories_object << { id: category[0], count: category[1], active: active || false }
end
categories.sort_by { |category| [category[:active] ? 0 : 1, -category[:count]] }
categories_object.sort_by { |category| [category[:active] ? 0 : 1, -category[:count]] }
end
def load_more_url