Skip to content

Commit ceac772

Browse files
authored
[Feature] implement search through given userIds (#564)
1 parent 20b1b35 commit ceac772

5 files changed

Lines changed: 77 additions & 7 deletions

File tree

src/main/java/com/itasocialacademy/oitassist/user/api/facade/UserFacadeImpl.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,12 @@ public Optional<UserProfileDetails> findProfileById(Long userId) {
9999
public List<UserProfileDetails> findProfilesByIds(List<Long> userIds) {
100100
return userService.findProfilesDetailsByIds(userIds);
101101
}
102+
103+
/**
104+
* {@inheritDoc}
105+
*/
106+
@Override
107+
public Optional<List<Long>> findUserIdsBySearchWithinIds(String search, List<Long> candidateIds) {
108+
return userService.findUserIdsBySearch(search, candidateIds);
109+
}
102110
}

src/main/java/com/itasocialacademy/oitassist/user/api/interfaces/UserFacade.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,21 @@ public interface UserFacade {
135135
* omitted from the result, consistent with {@link #findByIds}.
136136
*/
137137
List<UserProfileDetails> findProfilesByIds(List<Long> userIds);
138+
139+
/**
140+
* Filters a provided list of candidate user IDs based on a text search against
141+
* the user's first name, surname or email, required by {@code participation}
142+
* module.
143+
* <p>
144+
* This method is designed to perform a constrained search. Instead of searching
145+
* the entire database, it only searches within the provided
146+
* {@code candidateIds}.
147+
* </p>
148+
*
149+
* @param search the text search query (e.g., "Ivan", "ivan@email.com").
150+
* @param candidateIds the pool of user IDs to restrict the search to.
151+
* @return an {@code Optional} containing the filtered list of matching user
152+
* IDs, or {@code Optional.empty()} if the search string is null/blank.
153+
*/
154+
Optional<List<Long>> findUserIdsBySearchWithinIds(String search, List<Long> candidateIds);
138155
}

src/main/java/com/itasocialacademy/oitassist/user/dao/repository/UserRepository.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,19 @@ Page<User> findAllBySearchAndRoles(
4343
Pageable pageable);
4444

4545
Page<User> findAllByIdIn(List<Long> ids, Pageable pageable);
46+
47+
@Query("""
48+
SELECT u.id FROM User u
49+
WHERE u.id IN :candidateIds
50+
AND (
51+
:search IS NULL
52+
OR :search = ''
53+
OR LOWER(u.email) LIKE LOWER(CONCAT('%', :search, '%')) ESCAPE '\\'
54+
OR LOWER(u.firstName) LIKE LOWER(CONCAT('%', :search, '%')) ESCAPE '\\'
55+
OR LOWER(u.surname) LIKE LOWER(CONCAT('%', :search, '%')) ESCAPE '\\'
56+
OR LOWER(CONCAT(u.firstName, ' ', u.surname)) LIKE LOWER(CONCAT('%', :search, '%')) ESCAPE '\\'
57+
OR LOWER(CONCAT(u.surname, ' ', u.firstName)) LIKE LOWER(CONCAT('%', :search, '%')) ESCAPE '\\'
58+
)
59+
""")
60+
List<Long> findIdsBySearch(@Param("search") String search, @Param("candidateIds") List<Long> candidateIds);
4661
}

src/main/java/com/itasocialacademy/oitassist/user/service/UserServiceImpl.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,7 @@ public ResponseUserDTO changeUserRole(@NonNull Long userId, @NonNull Role newRol
122122
throw new InsufficientPermissionsException();
123123
}
124124

125-
String normalizedSearch = search == null || search.isBlank()
126-
? null
127-
: search.trim()
128-
.replaceAll("\\s+", " ")
129-
.replace("\\", "\\\\")
130-
.replace("%", "\\%")
131-
.replace("_", "\\_");
125+
String normalizedSearch = normalizeSearch(search);
132126

133127
List<Role> normalizedRoles = roles == null || roles.isEmpty()
134128
? null
@@ -167,4 +161,23 @@ public ResponseUserDTO changeUserRole(@NonNull Long userId, @NonNull Role newRol
167161
user.setUserStatus(newStatus);
168162
return mapper.toResponseUserDTO(repository.save(user));
169163
}
164+
165+
@Override
166+
public Optional<List<Long>> findUserIdsBySearch(String search, List<Long> candidateIds) {
167+
String normalizedSearch = normalizeSearch(search);
168+
if (normalizedSearch == null) {
169+
return Optional.empty();
170+
}
171+
return Optional.of(repository.findIdsBySearch(normalizedSearch, candidateIds));
172+
}
173+
174+
private String normalizeSearch(String search) {
175+
return search == null || search.isBlank()
176+
? null
177+
: search.trim()
178+
.replaceAll("\\s+", " ")
179+
.replace("\\", "\\\\")
180+
.replace("%", "\\%")
181+
.replace("_", "\\_");
182+
}
170183
}

src/main/java/com/itasocialacademy/oitassist/user/service/interfaces/UserService.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,21 @@ public interface UserService {
134134
*/
135135
@NonNull
136136
ResponseUserDTO changeUserStatus(@NonNull Long userId, @NonNull UserStatus newStatus);
137+
138+
/**
139+
* Filters a provided list of candidate user IDs based on a text search against
140+
* the user's first name, surname or email, required by
141+
* {@code UserFacade.findUserIdsBySearchWithinIds}.
142+
* <p>
143+
* This method is designed to perform a constrained search. Instead of searching
144+
* the entire database, it only searches within the provided
145+
* {@code candidateIds}.
146+
* </p>
147+
*
148+
* @param search the text search query (e.g., "Ivan", "ivan@email.com").
149+
* @param candidateIds the pool of user IDs to restrict the search to.
150+
* @return an {@code Optional} containing the filtered list of matching user
151+
* IDs, or {@code Optional.empty()} if the search string is null/blank.
152+
*/
153+
Optional<List<Long>> findUserIdsBySearch(String search, List<Long> candidateIds);
137154
}

0 commit comments

Comments
 (0)