From ef4f7edaf7e841727d5944028a977713674da5a4 Mon Sep 17 00:00:00 2001 From: Marcel Date: Sun, 7 Jun 2026 00:52:20 +0200 Subject: [PATCH] feat(person): match alias first names in searchByName (#763) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The direct-match classifier accepts alias firstName tokens, so the fetch must surface candidates matchable only via an alias first name. Add a.firstName to the searchByName LIKE clause (reuses the bound :query — injection-proof). The person_name_aliases.first_name column already exists; no migration. Co-Authored-By: Claude Opus 4.8 --- .../person/PersonRepository.java | 3 ++- .../person/PersonRepositoryTest.java | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/org/raddatz/familienarchiv/person/PersonRepository.java b/backend/src/main/java/org/raddatz/familienarchiv/person/PersonRepository.java index fe619e0b..0afc9e66 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/person/PersonRepository.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/person/PersonRepository.java @@ -19,7 +19,8 @@ public interface PersonRepository extends JpaRepository { "LOWER(CONCAT(COALESCE(p.firstName, ''),' ',p.lastName)) LIKE LOWER(CONCAT('%', :query, '%')) OR " + "LOWER(CONCAT(p.lastName, ' ', COALESCE(p.firstName, ''))) LIKE LOWER(CONCAT('%', :query, '%')) OR " + "LOWER(p.alias) LIKE LOWER(CONCAT('%', :query, '%')) OR " + - "LOWER(a.lastName) LIKE LOWER(CONCAT('%', :query, '%')) " + + "LOWER(a.lastName) LIKE LOWER(CONCAT('%', :query, '%')) OR " + + "LOWER(a.firstName) LIKE LOWER(CONCAT('%', :query, '%')) " + "ORDER BY p.lastName ASC, p.firstName ASC") List searchByName(@Param("query") String query); diff --git a/backend/src/test/java/org/raddatz/familienarchiv/person/PersonRepositoryTest.java b/backend/src/test/java/org/raddatz/familienarchiv/person/PersonRepositoryTest.java index e53366b9..131bfb1d 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/person/PersonRepositoryTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/person/PersonRepositoryTest.java @@ -428,6 +428,31 @@ class PersonRepositoryTest { assertThat(results).hasSize(1); } + @Test + void searchByName_findsByAliasFirstName() { + Person clara = personRepository.save(Person.builder().firstName("Clara").lastName("Cram").build()); + aliasRepository.save(PersonNameAlias.builder() + .person(clara).firstName("Wilhelmina").lastName("de Gruyter") + .type(PersonNameAliasType.BIRTH).sortOrder(0).build()); + + List results = personRepository.searchByName("Wilhelmina"); + + assertThat(results).hasSize(1); + assertThat(results.get(0).getLastName()).isEqualTo("Cram"); + } + + @Test + void searchByName_ordersByLastNameThenFirstName() { + personRepository.save(Person.builder().firstName("Clara").lastName("Cram").build()); + personRepository.save(Person.builder().firstName("Anna").lastName("Cram").build()); + personRepository.save(Person.builder().firstName("Bernd").lastName("Cram").build()); + + List results = personRepository.searchByName("Cram"); + + assertThat(results).extracting(Person::getFirstName) + .containsExactly("Anna", "Bernd", "Clara"); + } + // ─── searchWithDocumentCount with aliases ──────────────────────────────── @Test