From 110024245dde2af72b8eb482f88c364043985cfb Mon Sep 17 00:00:00 2001 From: Marcel Date: Mon, 6 Apr 2026 16:41:17 +0200 Subject: [PATCH] docs(search): document in-memory sort tradeoff and total=size() limitation Add TODO comment explaining why SENDER/RECEIVER sort is in-memory (JPA INNER JOIN drops null-sender docs) and note that pagination will require a DB COUNT query in DocumentSearchResult.of(). Co-Authored-By: Claude Sonnet 4.6 --- .../org/raddatz/familienarchiv/dto/DocumentSearchResult.java | 5 +++++ .../org/raddatz/familienarchiv/service/DocumentService.java | 3 +++ 2 files changed, 8 insertions(+) diff --git a/backend/src/main/java/org/raddatz/familienarchiv/dto/DocumentSearchResult.java b/backend/src/main/java/org/raddatz/familienarchiv/dto/DocumentSearchResult.java index 9ac03cca..a0c4af45 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/dto/DocumentSearchResult.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/dto/DocumentSearchResult.java @@ -5,6 +5,11 @@ import org.raddatz.familienarchiv.model.Document; import java.util.List; public record DocumentSearchResult(List documents, long total) { + /** + * Creates a result where total equals the list size. + * No pagination yet — the full matched set is always returned. + * When pagination is added, total must come from a DB COUNT query, not list.size(). + */ public static DocumentSearchResult of(List documents) { return new DocumentSearchResult(documents, documents.size()); } diff --git a/backend/src/main/java/org/raddatz/familienarchiv/service/DocumentService.java b/backend/src/main/java/org/raddatz/familienarchiv/service/DocumentService.java index aa9523a3..7d1bef2b 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/service/DocumentService.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/service/DocumentService.java @@ -292,6 +292,9 @@ public class DocumentService { .and(hasTagPartial(tagQ)) .and(hasStatus(status)); + // SENDER and RECEIVER are sorted in-memory because JPA's Sort.by("sender.lastName") + // generates an INNER JOIN that silently drops documents with null sender/receivers. + // TODO: replace with a native @Query using ORDER BY ... NULLS LAST when pagination is added. if (sort == DocumentSort.RECEIVER) { List results = documentRepository.findAll(spec); return sortByFirstReceiver(results, dir);