From de207ff3080fa5476e3ecd222cfca67b5e7fa9da Mon Sep 17 00:00:00 2001 From: Andrej Date: Thu, 7 Nov 2024 11:26:24 +0100 Subject: [PATCH] Improve speed for global search [SCI-11177] --- app/controllers/search_controller.rb | 2 +- app/models/concerns/searchable_model.rb | 2 +- app/models/protocol.rb | 18 ++++++++++++------ app/models/result.rb | 8 ++++---- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index afa8fd4e4b..8280193e08 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -92,7 +92,7 @@ def index @model = Protocol search_by_name({ in_repository: true }) - render json: @records, + render json: @records.includes(:team, :added_by), each_serializer: GlobalSearch::ProtocolSerializer, meta: { total: @records.total_count, diff --git a/app/models/concerns/searchable_model.rb b/app/models/concerns/searchable_model.rb index 5de3a84277..d18688cb57 100644 --- a/app/models/concerns/searchable_model.rb +++ b/app/models/concerns/searchable_model.rb @@ -115,7 +115,7 @@ module SearchableModel options[:raw_input].where(id: search_subquery(phrase[:query], options[:raw_input])) end query_clauses = if index.zero? - where(id: subquery_result) + subquery_result elsif phrase[:current_operator] == 'or' query_clauses.or(subquery_result) else diff --git a/app/models/protocol.rb b/app/models/protocol.rb index 7654e6f6e2..30552d5be5 100644 --- a/app/models/protocol.rb +++ b/app/models/protocol.rb @@ -157,11 +157,13 @@ def self.search(user, templates = latest_available_versions(teams) .with_granted_permissions(user, ProtocolPermissions::READ) templates = templates.active unless include_archived - templates.select(:id) + templates end || [] protocol_my_modules = if options[:options]&.dig(:in_repository).blank? protocols = viewable_by_user_my_module_protocols(user, teams) + .where(protocol_type: [Protocol.protocol_types[:unlinked], + Protocol.protocol_types[:linked]]) unless include_archived protocols = protocols.joins(my_module: { experiment: :project }) .active @@ -170,12 +172,16 @@ def self.search(user, projects: { archived: false }) end - protocols.select(:id) + protocols end || [] - protocols = Protocol.where('(protocols.protocol_type IN (?) AND protocols.id IN (?)) OR (protocols.id IN (?))', - [Protocol.protocol_types[:unlinked], Protocol.protocol_types[:linked]], - protocol_my_modules, protocol_templates) + protocols = if (options[:options]&.dig(:in_repository).present? || options[:options].blank?) && + options[:options]&.dig(:in_repository).blank? + where('protocols.id IN ((?) UNION ALL (?))', + protocol_templates.select(:id), protocol_my_modules.select(:id)) + else + options[:options]&.dig(:in_repository).blank? ? protocol_my_modules : Protocol.where(id: protocol_templates.pluck(:id)) + end protocols.where_attributes_like_boolean(SEARCHABLE_ATTRIBUTES, query, { with_subquery: true, raw_input: protocols }) end @@ -209,7 +215,7 @@ def self.latest_available_versions(teams) .where(protocol_type: Protocol.protocol_types[:in_repository_draft], parent_id: nil) .select(:id) - where('protocols.id IN ((?) UNION (?) UNION (?))', original_without_versions, published_versions, new_drafts) + where('protocols.id IN ((?) UNION ALL (?) UNION ALL (?))', original_without_versions, published_versions, new_drafts) end def self.viewable_by_user(user, teams, options = {}) diff --git a/app/models/result.rb b/app/models/result.rb index 6119458de7..86f1529460 100644 --- a/app/models/result.rb +++ b/app/models/result.rb @@ -48,8 +48,7 @@ def self.search(user, options = {}) teams = options[:teams] || current_team || user.teams.select(:id) - new_query = left_joins(:result_comments, :result_texts, result_tables: :table) - .joins(:my_module) + new_query = joins(:my_module) .where(my_modules: MyModule.with_granted_permissions(user, MyModulePermissions::READ) .where(user_assignments: { team: teams })) @@ -63,11 +62,12 @@ def self.search(user, new_query.where_attributes_like_boolean( SEARCHABLE_ATTRIBUTES, query, { with_subquery: true, raw_input: new_query } - ).distinct + ) end def self.search_subquery(query, raw_input) - raw_input.where_attributes_like_boolean(SEARCHABLE_ATTRIBUTES, query) + raw_input.left_joins(:result_comments, :result_texts, result_tables: :table) + .where_attributes_like_boolean(SEARCHABLE_ATTRIBUTES, query) end def duplicate(my_module, user, result_name: nil)