@@ -238,18 +238,27 @@ def search_score_sets(db: Session, owner_or_contributor: Optional[User], search:
238238 score_sets : list [ScoreSet ] = (
239239 query .join (ScoreSet .experiment )
240240 .options (
241+ # Use selectinload for ALL relationships loaded via the main query. The presence of
242+ # contains_eager disables SQLAlchemy's subquery-wrapping logic for the ENTIRE query,
243+ # not just the relationships nested inside it. This means any joinedload that adds a
244+ # LEFT OUTER JOIN to the main SQL query — even for many-to-one relationships — can
245+ # corrupt the LIMIT clause by applying it to joined rows rather than unique score sets,
246+ # causing fewer results than expected and suppressing the count query fallback.
247+ # The only JOINs that should remain in the main query are the explicit experiment
248+ # INNER JOIN (required by contains_eager) and the superseding score set LEFT OUTER JOIN
249+ # added by the filter builder.
241250 contains_eager (ScoreSet .experiment ).options (
242- joinedload (Experiment .experiment_set ),
243- joinedload (Experiment .keyword_objs ).joinedload (
251+ selectinload (Experiment .experiment_set ),
252+ selectinload (Experiment .keyword_objs ).joinedload (
244253 ExperimentControlledKeywordAssociation .controlled_keyword
245254 ),
246- joinedload (Experiment .created_by ),
247- joinedload (Experiment .modified_by ),
248- joinedload (Experiment .doi_identifiers ),
249- joinedload (Experiment .publication_identifier_associations ).joinedload (
255+ selectinload (Experiment .created_by ),
256+ selectinload (Experiment .modified_by ),
257+ selectinload (Experiment .doi_identifiers ),
258+ selectinload (Experiment .publication_identifier_associations ).joinedload (
250259 ExperimentPublicationIdentifierAssociation .publication
251260 ),
252- joinedload (Experiment .raw_read_identifiers ),
261+ selectinload (Experiment .raw_read_identifiers ),
253262 selectinload (Experiment .score_sets ).options (
254263 joinedload (ScoreSet .doi_identifiers ),
255264 joinedload (ScoreSet .publication_identifier_associations ).joinedload (
@@ -264,12 +273,12 @@ def search_score_sets(db: Session, owner_or_contributor: Optional[User], search:
264273 ),
265274 ),
266275 ),
267- joinedload (ScoreSet .license ),
268- joinedload (ScoreSet .doi_identifiers ),
269- joinedload (ScoreSet .publication_identifier_associations ).joinedload (
276+ selectinload (ScoreSet .license ),
277+ selectinload (ScoreSet .doi_identifiers ),
278+ selectinload (ScoreSet .publication_identifier_associations ).joinedload (
270279 ScoreSetPublicationIdentifierAssociation .publication
271280 ),
272- joinedload (ScoreSet .target_genes ).options (
281+ selectinload (ScoreSet .target_genes ).options (
273282 joinedload (TargetGene .ensembl_offset ).joinedload (EnsemblOffset .identifier ),
274283 joinedload (TargetGene .refseq_offset ).joinedload (RefseqOffset .identifier ),
275284 joinedload (TargetGene .uniprot_offset ).joinedload (UniprotOffset .identifier ),
@@ -292,7 +301,7 @@ def search_score_sets(db: Session, owner_or_contributor: Optional[User], search:
292301 # query.
293302 score_sets = score_sets [: search .limit ]
294303 count_query = db .query (ScoreSet )
295- build_search_score_sets_query_filter (db , count_query , owner_or_contributor , search )
304+ count_query = build_search_score_sets_query_filter (db , count_query , owner_or_contributor , search )
296305 num_score_sets = count_query .order_by (None ).limit (None ).count ()
297306
298307 save_to_logging_context ({"matching_resources" : num_score_sets })
0 commit comments