Skip to content

Commit

Permalink
ZFIN-9407: Use unaccent postgresql function to allow searches for a…
Browse files Browse the repository at this point in the history
…uthors with accented letters. (ZFIN#1221)

* Use `unaccent` postgresql function to allow searches for authors with accented letters.
* Use sets to avoid boilerplate duplication checks
* add to 1163/db.changelog.master.xml
  • Loading branch information
rtaylorzfin authored Nov 15, 2024
1 parent ab03257 commit 66c6a6d
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 36 deletions.
4 changes: 4 additions & 0 deletions source/org/zfin/db/postGmakePostloaddb/1163/ZFIN-9407.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
--liquibase formatted sql
--changeset rtaylor:ZFIN-9407.sql

CREATE EXTENSION unaccent;
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
<include file="source/org/zfin/db/postGmakePostloaddb/1163/ZFIN-9431.sql" />
<include file="source/org/zfin/db/postGmakePostloaddb/1163/ZFIN-9427.sql" />
<include file="source/org/zfin/db/postGmakePostloaddb/1163/ZFIN-9281.sql" />

<include file="source/org/zfin/db/postGmakePostloaddb/1163/ZFIN-9407.sql" />

</databaseChangeLog>

27 changes: 16 additions & 11 deletions source/org/zfin/profile/repository/HibernateProfileRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ public Person getPersonByName(String login) {
* */
public List<Person> getPeopleByFullName(String fullName) {
Session session = currentSession();
Query<Person> query = session.createQuery("from Person where fullName = :fullName", Person.class);
Query<Person> query = session.createQuery("from Person where unaccent(fullName) = unaccent(:fullName)", Person.class);
query.setParameter("fullName", fullName);
return query.list();
}
Expand Down Expand Up @@ -874,7 +874,7 @@ public List<Person> getPersonByLastNameStartsWith(String lastNameStartsWith) {
return currentSession().createQuery(hql, Person.class)
.list();
}
String hql = "from Person where lastName like :lastName order by lastName, firstName";
String hql = "from Person where unaccent(lastName) like unaccent(:lastName) order by lastName, firstName";
return currentSession().createQuery(hql, Person.class)
.setParameter("lastName", lastNameStartsWith + "%")
.list();
Expand All @@ -884,27 +884,27 @@ public List<Person> getPersonByLastNameStartsWith(String lastNameStartsWith) {
public List<Person> getPersonByLastNameStartsWithAndFirstNameStartsWith(String lastNameStartsWith, String firstNameStartsWith) {
String hql = """
from Person
where lower(lastName) like :lastName
AND lower(firstName) like :firstName
where lower(unaccent(lastName)) like lower(unaccent(:lastName))
AND lower(unaccent(firstName)) like lower(unaccent(:firstName))
ORDER BY lastName, firstName
""";
Query<Person> query = currentSession().createQuery(hql, Person.class);
query.setParameter("lastName", lastNameStartsWith.toLowerCase() + "%");
query.setParameter("firstName", firstNameStartsWith.toLowerCase() + "%");
query.setParameter("lastName", lastNameStartsWith + "%");
query.setParameter("firstName", firstNameStartsWith + "%");
return query.getResultList();
}

@Override
public List<Person> getPersonByLastNameEqualsAndFirstNameStartsWith(String lastName, String firstNameStartsWith) {
String hql = """
from Person
where lower(lastName) = :lastName
AND lower(firstName) like :firstName
where lower(unaccent(lastName)) = lower(unaccent(:lastName))
AND lower(unaccent(firstName)) like lower(unaccent(:firstName))
ORDER BY lastName, firstName
""";
Query<Person> query = currentSession().createQuery(hql, Person.class);
query.setParameter("lastName", lastName.toLowerCase());
query.setParameter("firstName", firstNameStartsWith.toLowerCase() + "%");
query.setParameter("lastName", lastName);
query.setParameter("firstName", firstNameStartsWith + "%");
return query.getResultList();
}

Expand Down Expand Up @@ -1039,7 +1039,12 @@ public List<Person> getStudents() {
@Override
public List<Person> getPersonByLastNameEquals(String lastName) {
Query<Person> query = currentSession()
.createQuery("from Person where lastName = :lastName ORDER BY fullName, firstName", Person.class);
.createQuery("""
from Person
where unaccent(lastName) = unaccent(:lastName)
ORDER BY fullName, firstName
""",
Person.class);
query.setParameter("lastName", lastName);
return query.list();
}
Expand Down
29 changes: 6 additions & 23 deletions source/org/zfin/publication/presentation/PublicationService.java
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ public List<String> splitAuthorListString(String authorListString) {
}

public List<Person> getAuthorSuggestions(String authorString) {
List<Person> suggestions = new ArrayList<>();
Set<Person> suggestions = new LinkedHashSet<>();

ProfileRepository profileRepository = RepositoryFactory.getProfileRepository();

Expand All @@ -290,34 +290,17 @@ public List<Person> getAuthorSuggestions(String authorString) {
lastName = authorString.split(",")[0];
firstInitial = authorString.split(",")[1].substring(1, 2);

for (Person person : profileRepository.getPersonByLastNameEqualsAndFirstNameStartsWith(lastName.trim(), firstInitial)) {
if (!suggestions.contains(person)) {
suggestions.add(person);
}
}
suggestions.addAll(profileRepository.getPersonByLastNameEqualsAndFirstNameStartsWith(lastName.trim(), firstInitial));
suggestions.addAll(profileRepository.getPersonByLastNameStartsWithAndFirstNameStartsWith(lastName.trim(), firstInitial));

for (Person person : profileRepository.getPersonByLastNameStartsWithAndFirstNameStartsWith(lastName.trim(), firstInitial)) {
if (!suggestions.contains(person)) {
suggestions.add(person);
}
}
} else {
lastName = authorString;
}

for (Person person : profileRepository.getPersonByLastNameEquals(lastName.trim())) {
if (!suggestions.contains(person)) {
suggestions.add(person);
}
}

for (Person person : profileRepository.getPersonByLastNameStartsWith(lastName.trim())) {
if (!suggestions.contains(person)) {
suggestions.add(person);
}
}
suggestions.addAll(profileRepository.getPersonByLastNameEquals(lastName.trim()));
suggestions.addAll(profileRepository.getPersonByLastNameStartsWith(lastName.trim()));

return suggestions;
return suggestions.stream().toList();
}

public PublicationFile processPublicationFile(Publication publication, String fileName, PublicationFileType fileType, InputStream fileData) throws IOException {
Expand Down
2 changes: 2 additions & 0 deletions test/org/zfin/publication/PublicationServiceSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class PublicationServiceSpec extends AbstractZfinIntegrationSpec{
public static String ZON = "ZDB-PERS-960805-635"
public static String KHOWE = "ZDB-PERS-001130-2"
public static String CKIM = "ZDB-PERS-970429-23"
public static String OZHAN = "ZDB-PERS-100120-1"

public def setupSpec() {
publicationService = new PublicationService();
Expand Down Expand Up @@ -69,6 +70,7 @@ class PublicationServiceSpec extends AbstractZfinIntegrationSpec{
"Zon, L." | ZON
"Howe, K." | KHOWE
"Kim, C.H." | CKIM
"Ozhan, Gunes" | OZHAN

}

Expand Down
45 changes: 45 additions & 0 deletions test/org/zfin/publication/PublicationServiceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.zfin.publication;

import org.junit.Test;
import org.zfin.AbstractDatabaseTest;
import org.zfin.profile.Person;
import org.zfin.publication.presentation.PublicationService;

import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.zfin.repository.RepositoryFactory.getProfileRepository;

public class PublicationServiceTest extends AbstractDatabaseTest {

@Test
public void testAuthorSuggestionWithAccents() {
List<String> queries = List.of("Ozhan, Gunes", "Ozhan, G", "Ozha, G", "Ozhan", "Ozha");
List<String> accentedQueries = List.of("Özhan, Günes", "Özhan, G", "Özha, G", "Özhan", "Özha");

Person author = getProfileRepository().getPerson("ZDB-PERS-100120-1");
PublicationService publicationService = new PublicationService();

List<Person> authorList;
for(String query : queries) {
authorList = publicationService.getAuthorSuggestions(query);
assertNotNull(authorList);
assertTrue(authorList.size() > 0);
assertTrue(authorList.contains(author));
}

for(String query : accentedQueries) {
authorList = publicationService.getAuthorSuggestions(query);
assertNotNull(authorList);
assertTrue(authorList.size() > 0);
assertTrue(authorList.contains(author));
}

authorList = publicationService.getAuthorSuggestions("Ozhan, Gunes");
assertNotNull(authorList);
assertEquals(1, authorList.size());
}
}

0 comments on commit 66c6a6d

Please sign in to comment.