Skip to content

Commit 5b9a515

Browse files
fix(FSADT1-1650): fixing order of query (#273)
Co-authored-by: Maria Martinez <maria.martinez@gov.bc.ca>
1 parent 4a1ea11 commit 5b9a515

File tree

4 files changed

+67
-38
lines changed

4 files changed

+67
-38
lines changed

src/main/java/ca/bc/gov/api/oracle/legacy/controller/ClientSearchController.java

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,11 @@ public Flux<ClientPublicViewDto> searchClients(
126126
* @param acronym the acronym of the client to search for (optional).
127127
* @param number the unique number of the client to search for (optional).
128128
* @param serverResponse the {@link ServerHttpResponse} to include response headers.
129-
* @return a reactive stream of {@link ClientPublicViewDto} objects representing matching
130-
* clients.
129+
* @return a reactive stream of {@link ClientPublicViewDto} objects representing matching
130+
* clients.
131131
*
132-
* @apiNote This method provides a paginated, fuzzy search for client details. Results
133-
* include a total record count in the response headers under {@code X-Total-Count}.
132+
* @apiNote This method provides a paginated, fuzzy search for client details. Results
133+
* include a total record count in the response headers under {@code X-Total-Count}.
134134
*/
135135
@GetMapping("/by")
136136
@Operation(
@@ -163,24 +163,28 @@ public Flux<ClientPublicViewDto> searchClients(
163163
}
164164
)
165165
public Flux<ClientPublicViewDto> searchByAcronymNameNumber(
166-
@Parameter(description = "The one index page number, defaults to 0", example = "0")
166+
@Parameter(description = "The one index page number, defaults to 0",
167+
example = "0")
167168
@RequestParam(value = "page", required = false, defaultValue = "0")
168169
Integer page,
169170

170171
@Parameter(description = "The amount of data to be returned per page, defaults to 10",
171-
example = "10")
172+
example = "10")
172173
@RequestParam(value = "size", required = false, defaultValue = "10")
173174
Integer size,
174175

175-
@Parameter(description = "The name of the client you're searching", example = "Western Forest Products")
176+
@Parameter(description = "The name of the client you're searching",
177+
example = "Western Forest Products")
176178
@RequestParam(value = "name", required = false)
177179
String name,
178180

179-
@Parameter(description = "The acronym of the client you're searching", example = "WFPS")
181+
@Parameter(description = "The acronym of the client you're searching",
182+
example = "WFPS")
180183
@RequestParam(value = "acronym", required = false)
181184
String acronym,
182185

183-
@Parameter(description = "The number of the client you're searching", example = "00000001")
186+
@Parameter(description = "The number of the client you're searching",
187+
example = "00000001")
184188
@RequestParam(value = "number", required = false)
185189
String number,
186190

@@ -190,7 +194,7 @@ public Flux<ClientPublicViewDto> searchByAcronymNameNumber(
190194
log.info("Searching for clients with name {}, acronym {}, number {}", name, acronym, number);
191195
return
192196
clientSearchService
193-
.searchByAcronymNameNumber(name, acronym, number)
197+
.searchByAcronymNameNumber(name, acronym, number, page, size)
194198
.flatMapMany(criteria -> clientSearchService.searchClientByQuery(criteria, page, size))
195199
.doOnNext(client -> log.info("Found client with id {}", client.getClientNumber()))
196200
.doOnNext(dto -> serverResponse.getHeaders()
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package ca.bc.gov.api.oracle.legacy.dto;
2+
3+
public interface SearchNumberScoreProjection {
4+
String getClientNumber();
5+
Integer getScore();
6+
}

src/main/java/ca/bc/gov/api/oracle/legacy/repository/ForestClientRepository.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package ca.bc.gov.api.oracle.legacy.repository;
22

3+
import ca.bc.gov.api.oracle.legacy.dto.SearchNumberScoreProjection;
34
import ca.bc.gov.api.oracle.legacy.entity.ForestClientEntity;
45
import org.springframework.data.domain.Pageable;
56
import org.springframework.data.r2dbc.repository.Query;
@@ -30,16 +31,23 @@ Mono<Long> countByClientNumberContainingOrClientNameContaining(String clientNumb
3031

3132
@Query(value = """
3233
SELECT
33-
CLIENT_NUMBER
34+
CLIENT_NUMBER,
35+
(
36+
CASE WHEN CLIENT_ACRONYM = :acronym THEN 800 ELSE 0 END +
37+
CASE WHEN CLIENT_NUMBER = :clientNumber THEN 1000 ELSE 0 END +
38+
UTL_MATCH.JARO_WINKLER_SIMILARITY(TRIM(COALESCE(LEGAL_FIRST_NAME || ' ', '') || TRIM(COALESCE(LEGAL_MIDDLE_NAME || ' ', '')) || COALESCE(CLIENT_NAME, '')), :clientName)
39+
) AS score
3440
FROM THE.FOREST_CLIENT
3541
WHERE
36-
UTL_MATCH.JARO_WINKLER_SIMILARITY(CLIENT_NAME, :clientName) >= 80
37-
OR UTL_MATCH.JARO_WINKLER_SIMILARITY(LEGAL_FIRST_NAME, :clientName) >= 80
38-
OR UTL_MATCH.JARO_WINKLER_SIMILARITY(LEGAL_MIDDLE_NAME, :clientName) >= 80
39-
OR UTL_MATCH.JARO_WINKLER_SIMILARITY(TRIM(COALESCE(LEGAL_FIRST_NAME || ' ', '') || TRIM(COALESCE(LEGAL_MIDDLE_NAME || ' ', '')) || COALESCE(CLIENT_NAME, '')), :clientName) >= 80
42+
UTL_MATCH.JARO_WINKLER_SIMILARITY(TRIM(COALESCE(LEGAL_FIRST_NAME || ' ', '') || TRIM(COALESCE(LEGAL_MIDDLE_NAME || ' ', '')) || COALESCE(CLIENT_NAME, '')), :clientName) >= 80
4043
OR CLIENT_ACRONYM = :acronym
4144
OR CLIENT_NUMBER = :clientNumber
42-
ORDER BY CLIENT_NUMBER""")
43-
Flux<String> searchNumberByNameAcronymNumber(String clientName, String acronym, String clientNumber);
44-
45+
ORDER BY score DESC
46+
OFFSET :offset ROWS FETCH NEXT :size ROWS ONLY""")
47+
Flux<SearchNumberScoreProjection> searchNumberByNameAcronymNumber(
48+
String clientName,
49+
String acronym,
50+
String clientNumber,
51+
long offset,
52+
int size);
4553
}

src/main/java/ca/bc/gov/api/oracle/legacy/service/ClientSearchService.java

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@
33
import static org.springframework.data.relational.core.query.Criteria.where;
44

55
import ca.bc.gov.api.oracle.legacy.dto.ClientPublicViewDto;
6+
import ca.bc.gov.api.oracle.legacy.dto.SearchNumberScoreProjection;
67
import ca.bc.gov.api.oracle.legacy.entity.ForestClientEntity;
78
import ca.bc.gov.api.oracle.legacy.repository.ForestClientRepository;
89
import ca.bc.gov.api.oracle.legacy.util.ClientMapper;
10+
import java.time.Duration;
911
import java.util.List;
1012
import lombok.RequiredArgsConstructor;
1113
import lombok.extern.slf4j.Slf4j;
1214
import org.apache.commons.lang3.StringUtils;
1315
import org.springframework.data.domain.PageRequest;
16+
import org.springframework.data.domain.Pageable;
1417
import org.springframework.data.domain.Sort;
1518
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
1619
import org.springframework.data.relational.core.query.Criteria;
@@ -110,41 +113,49 @@ public Flux<ClientPublicViewDto> searchClientByQuery(
110113
}
111114

112115
/**
113-
* Constructs a search {@link Criteria} object based on the provided client name, acronym, or
114-
* number.
115-
* This method normalizes input values for case-insensitive searches and validates the client
116-
* number.
116+
* Constructs a search {@link Criteria} object based on the provided client name, acronym, or
117+
* number. This method normalizes input values for case-insensitive searches and validates the
118+
* client number.
117119
*
118-
* @param name the name of the client to search for, or null if not specified.
120+
* @param name the name of the client to search for, or null if not specified.
119121
* @param acronym the acronym of the client to search for, or null if not specified.
120-
* @param number the unique number of the client to search for, or null if not specified.
122+
* @param number the unique number of the client to search for, or null if not specified.
123+
* @param size the number of results to return.
121124
* @return a {@link Mono} emitting the constructed {@link Criteria} object for the search.
122-
*
123-
* @implNote Input values are transformed to uppercase for case-insensitivity. The client
124-
* number is validated using {@link #checkClientNumber(String)}. Repository results are
125-
* mapped to a search criteria object.
125+
* @implNote Input values are transformed to uppercase for case-insensitivity. The client number
126+
* is validated using {@link #checkClientNumber(String)}. Repository results are mapped to a
127+
* search criteria object.
126128
*/
127-
public Mono<Criteria> searchByAcronymNameNumber(String name, String acronym, String number) {
129+
public Mono<Criteria> searchByAcronymNameNumber(
130+
String name,
131+
String acronym,
132+
String number,
133+
int page,
134+
int size) {
128135
log.info("Searching for clients with name {}, acronym {} or number {}", name, acronym, number);
129136

130137
String searchName = StringUtils.isNotBlank(name) ? name.toUpperCase() : null;
131138
String searchAcronym = StringUtils.isNotBlank(acronym) ? acronym.toUpperCase() : null;
132139
String searchNumber = StringUtils.isNotBlank(number) ? checkClientNumber(number) : null;
140+
Pageable pageRequest = PageRequest.of(page, size);
133141

134142
return
135-
forestClientRepository
136-
.searchNumberByNameAcronymNumber(
137-
searchName,
138-
searchAcronym,
139-
searchNumber
140-
)
141-
.collectList()
142-
.map(this::searchById);
143+
forestClientRepository
144+
.searchNumberByNameAcronymNumber(
145+
searchName,
146+
searchAcronym,
147+
searchNumber,
148+
pageRequest.getOffset(),
149+
pageRequest.getPageSize()
150+
)
151+
.map(SearchNumberScoreProjection::getClientNumber)
152+
.collectList()
153+
.map(this::searchById);
143154

144155
}
145156

146157
private String checkClientNumber(String clientNumber) {
147-
if(StringUtils.isBlank(clientNumber)) {
158+
if (StringUtils.isBlank(clientNumber)) {
148159
return clientNumber;
149160
}
150161

0 commit comments

Comments
 (0)