diff --git a/app/assets/javascripts/discourse/app/lib/search.js b/app/assets/javascripts/discourse/app/lib/search.js index 9331a85076b..2bcde5f5b73 100644 --- a/app/assets/javascripts/discourse/app/lib/search.js +++ b/app/assets/javascripts/discourse/app/lib/search.js @@ -9,6 +9,7 @@ import userSearch from "discourse/lib/user-search"; import { escapeExpression } from "discourse/lib/utilities"; import Category from "discourse/models/category"; import Post from "discourse/models/post"; +import Site from "discourse/models/site"; import Topic from "discourse/models/topic"; import User from "discourse/models/user"; import getURL from "discourse-common/lib/get-url"; @@ -56,10 +57,15 @@ export function translateResults(results, opts) { results.categories = results.categories .map(function (category) { + Site.current().updateCategory(category); return Category.list().findBy("id", category.id || category.model.id); }) .compact(); + results.grouped_search_result?.extra?.categories?.forEach((category) => + Site.current().updateCategory(category) + ); + results.groups = results.groups .map((group) => { const name = escapeExpression(group.name); diff --git a/app/serializers/grouped_search_result_serializer.rb b/app/serializers/grouped_search_result_serializer.rb index 66c49602693..fe7afd55ea6 100644 --- a/app/serializers/grouped_search_result_serializer.rb +++ b/app/serializers/grouped_search_result_serializer.rb @@ -13,7 +13,8 @@ class GroupedSearchResultSerializer < ApplicationSerializer :search_log_id, :more_full_page_results, :can_create_topic, - :error + :error, + :extra def search_log_id object.search_log_id @@ -30,4 +31,17 @@ class GroupedSearchResultSerializer < ApplicationSerializer def can_create_topic scope.can_create?(Topic) end + + def extra + extra = {} + + if object.can_lazy_load_categories + extra[:categories] = ActiveModel::ArraySerializer.new( + object.extra_categories, + each_serializer: BasicCategorySerializer, + ) + end + + extra + end end diff --git a/lib/search.rb b/lib/search.rb index 88379952939..557a2bb6c88 100644 --- a/lib/search.rb +++ b/lib/search.rb @@ -266,6 +266,7 @@ class Search search_context: @search_context, blurb_length: @blurb_length, is_header_search: !use_full_page_limit, + can_lazy_load_categories: @guardian.can_lazy_load_categories?, ) end @@ -1447,7 +1448,7 @@ class Search def posts_eager_loads(query) query = query.includes(:user, :post_search_data) - topic_eager_loads = [:category] + topic_eager_loads = [{ category: :parent_category }] topic_eager_loads << :tags if SiteSetting.tagging_enabled diff --git a/lib/search/grouped_search_results.rb b/lib/search/grouped_search_results.rb index 0fbe7fbb636..05da9722681 100644 --- a/lib/search/grouped_search_results.rb +++ b/lib/search/grouped_search_results.rb @@ -14,6 +14,7 @@ class Search :type_filter, :posts, :categories, + :extra_categories, :users, :tags, :groups, @@ -25,6 +26,7 @@ class Search :more_full_page_results, :error, :use_pg_headlines_for_excerpt, + :can_lazy_load_categories, ) attr_accessor :search_log_id @@ -38,7 +40,8 @@ class Search blurb_length: nil, blurb_term: nil, is_header_search: false, - use_pg_headlines_for_excerpt: SiteSetting.use_pg_headlines_for_excerpt + use_pg_headlines_for_excerpt: SiteSetting.use_pg_headlines_for_excerpt, + can_lazy_load_categories: false ) @type_filter = type_filter @term = term @@ -47,12 +50,14 @@ class Search @blurb_length = blurb_length || BLURB_LENGTH @posts = [] @categories = [] + @extra_categories = Set.new @users = [] @tags = [] @groups = [] @error = nil @is_header_search = is_header_search @use_pg_headlines_for_excerpt = use_pg_headlines_for_excerpt + @can_lazy_load_categories = can_lazy_load_categories end def error=(error) @@ -101,6 +106,21 @@ class Search else (self.public_send(type)) << object end + + if can_lazy_load_categories + category = + case type + when "posts" + object.topic.category + when "topics" + object.category + end + + if category + extra_categories << category.parent_category if category.parent_category + extra_categories << category + end + end end def self.blurb_for(cooked: nil, term: nil, blurb_length: BLURB_LENGTH, scrub: true) diff --git a/spec/requests/api/schemas/json/search_response.json b/spec/requests/api/schemas/json/search_response.json index 992c239a1ce..12a87342136 100644 --- a/spec/requests/api/schemas/json/search_response.json +++ b/spec/requests/api/schemas/json/search_response.json @@ -74,6 +74,17 @@ "null" ] }, + "extra": { + "type": "object", + "properties": { + "categories": { + "type": [ + "array", + "null" + ] + } + } + }, "post_ids": { "type": "array", "items": { diff --git a/spec/requests/search_controller_spec.rb b/spec/requests/search_controller_spec.rb index fcedd413855..5685d7489f4 100644 --- a/spec/requests/search_controller_spec.rb +++ b/spec/requests/search_controller_spec.rb @@ -495,6 +495,39 @@ RSpec.describe SearchController do end end end + + context "with lazy loaded categories" do + fab!(:parent_category) { Fabricate(:category) } + fab!(:category) { Fabricate(:category, parent_category: parent_category) } + fab!(:other_category) { Fabricate(:category, parent_category: parent_category) } + + fab!(:post) do + with_search_indexer_enabled do + topic = Fabricate(:topic, category: category) + Fabricate(:post, topic: topic, raw: "hello world. first topic") + end + end + + fab!(:other_post) do + with_search_indexer_enabled do + topic = Fabricate(:topic, category: other_category) + Fabricate(:post, topic: topic, raw: "hello world. second topic") + end + end + + before { SiteSetting.lazy_load_categories_groups = "#{Group::AUTO_GROUPS[:everyone]}" } + + it "returns extra categories and parent categories" do + get "/search.json", params: { q: "hello" } + + categories = response.parsed_body["grouped_search_result"]["extra"]["categories"] + expect(categories.map { |c| c["id"] }).to contain_exactly( + parent_category.id, + category.id, + other_category.id, + ) + end + end end context "with search priority" do