From b12a45275c93501cedcdb6181583ef87330c2444 Mon Sep 17 00:00:00 2001 From: Ross Date: Wed, 5 Nov 2025 22:08:54 +0000 Subject: [PATCH] Enhance case search results display to include series modalities and examinations --- .../atlas/partials/_case_search_results.html | 19 +++++++++ atlas/views.py | 39 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/atlas/templates/atlas/partials/_case_search_results.html b/atlas/templates/atlas/partials/_case_search_results.html index aae32b16..072e7390 100644 --- a/atlas/templates/atlas/partials/_case_search_results.html +++ b/atlas/templates/atlas/partials/_case_search_results.html @@ -7,6 +7,25 @@
{{ case.title }}
{{ case.created_date|date:"Y-m-d" }} +
+ {% if case.author.all %}By {{ case.author.all|join:", " }}{% endif %} + {% if case.condition %}{{ case.condition.name }}{% endif %} + {% if case.presentation %}{{ case.presentation.name }}{% endif %} + {% if case.subspecialty %}{{ case.subspecialty.name }}{% endif %} +
+ +
+ {# show up to three series modalities/examinations if present #} + {% for s in case.series.all|slice:":3" %} + + {% if s.modality %}{{ s.modality.modality }}{% endif %} + {% if s.examination %} / {{ s.examination.examination }}{% endif %} + + {% empty %} + No series + {% endfor %} +
+

{{ case.description }}

{% endfor %} diff --git a/atlas/views.py b/atlas/views.py index 6c5cd75f..bf062f5b 100755 --- a/atlas/views.py +++ b/atlas/views.py @@ -191,6 +191,45 @@ def case_search_partial(request): the index page. It respects the user's available cases via get_cases_available_to_user. """ + # NOTE (search migration): + # + # This view currently performs simple `__icontains` lookups across Case + # fields and related models. For better relevance and performance you can + # migrate this to use PostgreSQL full-text search (FTS). Recommended steps: + # + # 1) Enable optional Postgres extensions (if you want trigram/unaccent): + # - Add migrations: `TrigramExtension()` and optionally `UnaccentExtension()` + # from `django.contrib.postgres.operations`. + # + # 2) Create a tsvector expression index (recommended) or add a + # SearchVectorField on the Case model. Example expression index SQL: + # CREATE INDEX CONCURRENTLY idx_case_search ON atlas_case + # USING GIN (to_tsvector('english', coalesce(title,'') || ' ' || + # coalesce(description,'') || ' ' || coalesce(history,''))); + # + # Alternatively use a Django migration with `GinIndex` on an + # `SearchVectorField` or a `Func` expression. + # + # 3) Query using django.contrib.postgres.search utilities. Example: + # from django.contrib.postgres.search import ( + # SearchVector, SearchQuery, SearchRank + # ) + # sv = (SearchVector('title', weight='A') + + # SearchVector('description', weight='B') + + # SearchVector('history', weight='C')) + # sq = SearchQuery(q) + # qs = Case.objects.annotate(search=sv).filter(search=sq) + # .annotate(rank=SearchRank(F('search'), sq)).order_by('-rank') + # + # 4) For interactive/fuzzy typing consider pg_trgm (TrigramExtension) + # and `TrigramSimilarity` as a fallback when FTS returns few results. + # + # 5) Keep in mind to re-index (or recreate indexes) when you change + # the fields included in the tsvector. Use concurrent index creation + # for minimal downtime. + # + # If you want, I can prepare the migration, model/index changes and a + # Django-code example to wire FTS into this view and tune weights. q = request.GET.get('q', '') or request.GET.get('case-search-input', '') q = q.strip()