From 9199c52e5e41a6a6376d10d83ab6e59425c2951a Mon Sep 17 00:00:00 2001 From: Bianca Nenciu Date: Wed, 21 Feb 2024 17:29:47 +0200 Subject: [PATCH] FIX: Load categories with search topic results (#25700) Add categories to the serialized search results together with the topics when lazy load categories is enabled. This is necessary in order for the results to be rendered correctly and display the category information. --- .../javascripts/discourse/app/lib/search.js | 6 ++++ .../grouped_search_result_serializer.rb | 16 ++++++++- lib/search.rb | 3 +- lib/search/grouped_search_results.rb | 22 ++++++++++++- .../api/schemas/json/search_response.json | 11 +++++++ spec/requests/search_controller_spec.rb | 33 +++++++++++++++++++ 6 files changed, 88 insertions(+), 3 deletions(-) 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