From 63311eceb07651a9aa9b4d1737500d1b19048236 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 19 May 2021 14:52:54 +0200 Subject: [PATCH] avoid serializing long id list in case of huge procedure, search on it before --- app/controllers/recherche_controller.rb | 17 ++++++++--------- app/services/dossier_search_service.rb | 20 ++++++++++++-------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/app/controllers/recherche_controller.rb b/app/controllers/recherche_controller.rb index 6d02bcbea..f2d96ffb6 100644 --- a/app/controllers/recherche_controller.rb +++ b/app/controllers/recherche_controller.rb @@ -10,25 +10,24 @@ class RechercheController < ApplicationController def index @search_terms = search_terms - @instructeur_dossiers_ids = current_instructeur&.dossiers&.ids || [] - matching_dossiers_ids = DossierSearchService - .matching_dossiers(@instructeur_dossiers_ids, @search_terms, with_annotation: true) - .to_set + @instructeur_dossiers_ids = DossierSearchService + .matching_dossiers(current_instructeur&.dossiers, @search_terms, with_annotation: true) - @dossier_avis_ids_h = current_expert&.avis&.pluck(:dossier_id, :id).to_h || {} - expert_dossiers_ids = @dossier_avis_ids_h.keys - matching_dossiers_ids.merge(DossierSearchService.matching_dossiers(expert_dossiers_ids, @search_terms)) + expert_dossier_ids = DossierSearchService + .matching_dossiers(current_expert&.dossiers, @search_terms) - @dossiers_count = matching_dossiers_ids.count + matching_dossiers_ids = (@instructeur_dossiers_ids + expert_dossier_ids).uniq @paginated_ids = Kaminari - .paginate_array(matching_dossiers_ids.to_a) + .paginate_array(matching_dossiers_ids) .page(page) .per(ITEMS_PER_PAGE) @projected_dossiers = DossierProjectionService.project(@paginated_ids, PROJECTIONS) + @dossiers_count = matching_dossiers_ids.count @followed_dossiers_id = current_instructeur&.followed_dossiers&.where(id: @paginated_ids)&.ids || [] + @dossier_avis_ids_h = current_expert&.avis&.where(dossier_id: @paginated_ids)&.pluck(:dossier_id, :id).to_h || {} end private diff --git a/app/services/dossier_search_service.rb b/app/services/dossier_search_service.rb index dc5eab1a1..a3f95a3f5 100644 --- a/app/services/dossier_search_service.rb +++ b/app/services/dossier_search_service.rb @@ -1,7 +1,11 @@ class DossierSearchService - def self.matching_dossiers(ids, search_terms, with_annotations = false) - dossier_by_exact_id(ids, search_terms) - .presence || dossier_by_full_text(ids, search_terms, with_annotations) + def self.matching_dossiers(dossiers, search_terms, with_annotations = false) + if dossiers.nil? + [] + else + dossier_by_exact_id(dossiers, search_terms) + .presence || dossier_by_full_text(dossiers, search_terms, with_annotations) + end end def self.matching_dossiers_for_user(search_terms, user) @@ -11,20 +15,20 @@ class DossierSearchService private - def self.dossier_by_exact_id(ids, search_terms) + def self.dossier_by_exact_id(dossiers, search_terms) id = search_terms.to_i if id != 0 && id_compatible?(id) # Sometimes instructeur is searching dossiers with a big number (ex: SIRET), ActiveRecord can't deal with them and throws ActiveModel::RangeError. id_compatible? prevents this. - ids.filter { |dossier_id| dossier_id == id }.uniq + dossiers.where(id: id).ids else - Dossier.none + [] end end - def self.dossier_by_full_text(ids, search_terms, with_annotations) + def self.dossier_by_full_text(dossiers, search_terms, with_annotations) ts_vector = "to_tsvector('french', #{with_annotations ? 'dossiers.search_terms || dossiers.private_search_terms' : 'dossiers.search_terms'})" ts_query = "to_tsquery('french', #{Dossier.connection.quote(to_tsquery(search_terms))})" - Dossier.where(id: ids) + dossiers .where("#{ts_vector} @@ #{ts_query}") .order(Arel.sql("COALESCE(ts_rank(#{ts_vector}, #{ts_query}), 0) DESC")) .pluck('id')