Skip to content

Commit d5a26ff

Browse files
authored
Merge pull request #2303 from bcgov/feature/ALCS-2212
ALCS-2212: Improve advanced search name field
2 parents 5fd74a2 + f5fc9a6 commit d5a26ff

File tree

7 files changed

+84
-81
lines changed

7 files changed

+84
-81
lines changed

services/apps/alcs/src/alcs/search/inquiry/inquiry-advanced-search.service.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Injectable, Logger } from '@nestjs/common';
33
import { InjectRepository } from '@nestjs/typeorm';
44
import * as hash from 'object-hash';
55
import { QueryRunner, Repository } from 'typeorm';
6-
import { formatStringToPostgresSearchStringArrayWithWildCard } from '../../../utils/search-helper';
6+
import { formatNameSearchString } from '../../../utils/search-helper';
77
import { processSearchPromises } from '../../../utils/search/search-intersection';
88
import { InquiryParcel } from '../../inquiry/inquiry-parcel/inquiry-parcel.entity';
99
import { Inquiry } from '../../inquiry/inquiry.entity';
@@ -192,21 +192,21 @@ export class InquiryAdvancedSearchService {
192192
}
193193

194194
private addNameResults(searchDto: SearchRequestDto, promises: Promise<{ fileNumber: string }[]>[]) {
195-
const formattedSearchString = formatStringToPostgresSearchStringArrayWithWildCard(searchDto.name!);
195+
const formattedSearchString = formatNameSearchString(searchDto.name!);
196196
const promise = this.inquiryRepository
197197
.createQueryBuilder('inquiry')
198198
.select('inquiry.fileNumber')
199-
.where("LOWER(inquiry.inquirer_first_name || ' ' || inquiry.inquirer_last_name) LIKE ANY (:names)", {
200-
names: formattedSearchString,
199+
.where("LOWER(CONCAT_WS(' ', inquiry.inquirer_first_name, inquiry.inquirer_last_name)) LIKE :name", {
200+
name: formattedSearchString,
201201
})
202-
.orWhere('LOWER(inquiry.inquirer_first_name) LIKE ANY (:names)', {
203-
names: formattedSearchString,
202+
.orWhere('LOWER(inquiry.inquirer_first_name) LIKE :name', {
203+
name: formattedSearchString,
204204
})
205-
.orWhere('LOWER(inquiry.inquirer_last_name) LIKE ANY (:names)', {
206-
names: formattedSearchString,
205+
.orWhere('LOWER(inquiry.inquirer_last_name) LIKE :name', {
206+
name: formattedSearchString,
207207
})
208-
.orWhere('LOWER(inquiry.inquirer_organization) LIKE ANY (:names)', {
209-
names: formattedSearchString,
208+
.orWhere('LOWER(inquiry.inquirer_organization) LIKE :name', {
209+
name: formattedSearchString,
210210
})
211211
.getMany();
212212
promises.push(promise);

services/apps/alcs/src/alcs/search/planning-review/planning-review-advanced-search.service.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm';
44
import * as hash from 'object-hash';
55
import { QueryRunner, Repository } from 'typeorm';
66
import { getNextDayToPacific, getStartOfDayToPacific } from '../../../utils/pacific-date-time-helper';
7-
import { formatStringToPostgresSearchStringArrayWithWildCard } from '../../../utils/search-helper';
7+
import { formatNameSearchString } from '../../../utils/search-helper';
88
import { processSearchPromises } from '../../../utils/search/search-intersection';
99
import { LocalGovernment } from '../../local-government/local-government.entity';
1010
import { PlanningReferral } from '../../planning-review/planning-referral/planning-referral.entity';
@@ -196,13 +196,13 @@ export class PlanningReviewAdvancedSearchService {
196196
}
197197

198198
private addNameResults(searchDto: SearchRequestDto, promises: Promise<{ fileNumber: string }[]>[]) {
199-
const formattedSearchString = formatStringToPostgresSearchStringArrayWithWildCard(searchDto.name!);
199+
const formattedSearchString = formatNameSearchString(searchDto.name!);
200200

201201
const promise = this.planningReviewRepository
202202
.createQueryBuilder('planningReview')
203203
.select('planningReview.fileNumber')
204-
.where('LOWER(planningReview.document_name) LIKE ANY (:names)', {
205-
names: formattedSearchString,
204+
.where('LOWER(planningReview.document_name) LIKE :name', {
205+
name: formattedSearchString,
206206
})
207207
.getMany();
208208
promises.push(promise);
Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,37 @@
1-
import { formatStringToPostgresSearchStringArrayWithWildCard } from './search-helper';
1+
import { formatNameSearchString } from './search-helper';
22

33
describe('formatStringToSearchStringWithWildCard', () => {
44
test('should format string correctly when input contains single word', () => {
55
const input = 'word';
6-
const expectedOutput = '{%word%}';
7-
const actualOutput =
8-
formatStringToPostgresSearchStringArrayWithWildCard(input);
6+
const expectedOutput = 'word';
7+
const actualOutput = formatNameSearchString(input);
98
expect(actualOutput).toBe(expectedOutput);
109
});
1110

1211
test('should format string correctly when input contains multiple words', () => {
1312
const input = 'multiple words';
14-
const expectedOutput = '{%multiple%,%words%,%multiple words%}';
15-
const actualOutput =
16-
formatStringToPostgresSearchStringArrayWithWildCard(input);
13+
const expectedOutput = 'multiple words';
14+
const actualOutput = formatNameSearchString(input);
15+
expect(actualOutput).toBe(expectedOutput);
16+
});
17+
18+
test('should format string correctly when input contains ending wildcards', () => {
19+
const input = 'multiple %words';
20+
const expectedOutput = 'multiple %words';
21+
const actualOutput = formatNameSearchString(input);
1722
expect(actualOutput).toBe(expectedOutput);
1823
});
1924

2025
test('should trim input and format string correctly', () => {
2126
const input = ' trimmed word ';
22-
const expectedOutput = '{%trimmed%,%word%,%trimmed word%}';
23-
const actualOutput =
24-
formatStringToPostgresSearchStringArrayWithWildCard(input);
27+
const expectedOutput = 'trimmed word';
28+
const actualOutput = formatNameSearchString(input);
2529
expect(actualOutput).toBe(expectedOutput);
2630
});
2731

2832
it('should handle empty string correctly', () => {
2933
const input = '';
30-
const expectedOutput = '{%%}';
31-
expect(formatStringToPostgresSearchStringArrayWithWildCard(input)).toBe(
32-
expectedOutput,
33-
);
34+
const expectedOutput = '';
35+
expect(formatNameSearchString(input)).toBe(expectedOutput);
3436
});
3537
});
Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
export const formatStringToPostgresSearchStringArrayWithWildCard = (
2-
input: string,
3-
): string => {
4-
input = input.trim();
5-
const splitString = input.split(' ');
6-
let output = '';
1+
export const formatNameSearchString = (input: string): string | null => {
2+
return input
3+
.split(/\s+/)
4+
.filter((word) => word !== '')
5+
.map((word) => {
6+
const matches = word
7+
.toLowerCase()
8+
.match(/^(\%)?([^\s]+?)(\%)?$/)
9+
?.map((match) => match ?? '');
710

8-
if (splitString.length === 1) {
9-
output = splitString.map((word) => `%${word}%`.toLowerCase()).join(',');
10-
return `{${output}}`;
11-
}
11+
if (!matches) {
12+
return null;
13+
}
1214

13-
output = splitString
14-
.map((word) => `%${word}%`.trim().toLowerCase())
15-
.join(',');
16-
output += `,%${input}%`;
17-
return `{${output}}`;
15+
return matches[1] + matches[2].replace(/%/g, '') + matches[3];
16+
})
17+
.join(' ');
1818
};

services/apps/alcs/src/utils/search/application-search-filters.ts

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { ApplicationParcel } from '../../portal/application-submission/applicati
88
import { ApplicationSubmission } from '../../portal/application-submission/application-submission.entity';
99
import { InboxRequestDto } from '../../portal/inbox/inbox.dto';
1010
import { SearchRequestDto } from '../../portal/public/search/public-search.dto';
11-
import { formatStringToPostgresSearchStringArrayWithWildCard } from '../search-helper';
11+
import { formatNameSearchString } from '../search-helper';
1212

1313
export const APP_SEARCH_FILTERS = {
1414
addFileNumberResults: (
@@ -98,29 +98,30 @@ export const APP_SEARCH_FILTERS = {
9898
searchDto: SearchRequestDto | InboxRequestDto,
9999
applicationSubmissionRepository: Repository<ApplicationSubmission>,
100100
) => {
101-
const formattedSearchString = formatStringToPostgresSearchStringArrayWithWildCard(searchDto.name!);
102-
return applicationSubmissionRepository
101+
const formattedSearchString = formatNameSearchString(searchDto.name!);
102+
103+
let query = applicationSubmissionRepository
103104
.createQueryBuilder('appSub')
104105
.select('appSub.fileNumber')
105106
.leftJoin(ApplicationOwner, 'application_owner', 'application_owner.application_submission_uuid = appSub.uuid')
106107
.andWhere(
107-
new Brackets((qb) =>
108-
qb
109-
.where("LOWER(application_owner.first_name || ' ' || application_owner.last_name) LIKE ANY (:names)", {
110-
names: formattedSearchString,
108+
new Brackets((qb) => {
109+
qb.where("LOWER(CONCAT_WS(' ', application_owner.first_name, application_owner.last_name)) LIKE :name", {
110+
name: formattedSearchString,
111+
})
112+
.orWhere('LOWER(application_owner.first_name) LIKE :name', {
113+
name: formattedSearchString,
111114
})
112-
.orWhere('LOWER(application_owner.first_name) LIKE ANY (:names)', {
113-
names: formattedSearchString,
115+
.orWhere('LOWER(application_owner.last_name) LIKE :name', {
116+
name: formattedSearchString,
114117
})
115-
.orWhere('LOWER(application_owner.last_name) LIKE ANY (:names)', {
116-
names: formattedSearchString,
117-
})
118-
.orWhere('LOWER(application_owner.organization_name) LIKE ANY (:names)', {
119-
names: formattedSearchString,
120-
}),
121-
),
122-
)
123-
.getMany();
118+
.orWhere('LOWER(application_owner.organization_name) LIKE :name', {
119+
name: formattedSearchString,
120+
});
121+
}),
122+
);
123+
124+
return query.getMany();
124125
},
125126
addGovernmentResults: async (
126127
searchDto: SearchRequestDto,

services/apps/alcs/src/utils/search/notice-of-intent-search-filters.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { NoticeOfIntentOwner } from '../../portal/notice-of-intent-submission/no
66
import { NoticeOfIntentParcel } from '../../portal/notice-of-intent-submission/notice-of-intent-parcel/notice-of-intent-parcel.entity';
77
import { NoticeOfIntentSubmission } from '../../portal/notice-of-intent-submission/notice-of-intent-submission.entity';
88
import { SearchRequestDto } from '../../portal/public/search/public-search.dto';
9-
import { formatStringToPostgresSearchStringArrayWithWildCard } from '../search-helper';
9+
import { formatNameSearchString } from '../search-helper';
1010

1111
export const NOI_SEARCH_FILTERS = {
1212
addFileNumberResults: (searchDto: SearchRequestDto | InboxRequestDto, noiRepository: Repository<NoticeOfIntent>) => {
@@ -81,7 +81,7 @@ export const NOI_SEARCH_FILTERS = {
8181
searchDto: SearchRequestDto | InboxRequestDto,
8282
noiSubmissionRepository: Repository<NoticeOfIntentSubmission>,
8383
) => {
84-
const formattedSearchString = formatStringToPostgresSearchStringArrayWithWildCard(searchDto.name!);
84+
const formattedSearchString = formatNameSearchString(searchDto.name!);
8585
return noiSubmissionRepository
8686
.createQueryBuilder('noiSub')
8787
.select('noiSub.fileNumber')
@@ -94,19 +94,19 @@ export const NOI_SEARCH_FILTERS = {
9494
new Brackets((qb) =>
9595
qb
9696
.where(
97-
"LOWER(notice_of_intent_owner.first_name || ' ' || notice_of_intent_owner.last_name) LIKE ANY (:names)",
97+
"LOWER(CONCAT_WS(' ', notice_of_intent_owner.first_name, notice_of_intent_owner.last_name)) LIKE :name",
9898
{
99-
names: formattedSearchString,
99+
name: formattedSearchString,
100100
},
101101
)
102-
.orWhere('LOWER(notice_of_intent_owner.first_name) LIKE ANY (:names)', {
103-
names: formattedSearchString,
102+
.orWhere('LOWER(notice_of_intent_owner.first_name) LIKE :name', {
103+
name: formattedSearchString,
104104
})
105-
.orWhere('LOWER(notice_of_intent_owner.last_name) LIKE ANY (:names)', {
106-
names: formattedSearchString,
105+
.orWhere('LOWER(notice_of_intent_owner.last_name) LIKE :name', {
106+
name: formattedSearchString,
107107
})
108-
.orWhere('LOWER(notice_of_intent_owner.organization_name) LIKE ANY (:names)', {
109-
names: formattedSearchString,
108+
.orWhere('LOWER(notice_of_intent_owner.organization_name) LIKE :name', {
109+
name: formattedSearchString,
110110
}),
111111
),
112112
)

services/apps/alcs/src/utils/search/notification-search-filters.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { NotificationParcel } from '../../portal/notification-submission/notific
66
import { NotificationSubmission } from '../../portal/notification-submission/notification-submission.entity';
77
import { NotificationTransferee } from '../../portal/notification-submission/notification-transferee/notification-transferee.entity';
88
import { SearchRequestDto } from '../../portal/public/search/public-search.dto';
9-
import { formatStringToPostgresSearchStringArrayWithWildCard } from '../search-helper';
9+
import { formatNameSearchString } from '../search-helper';
1010

1111
export const NOTIFICATION_SEARCH_FILTERS = {
1212
addFileNumberResults: (
@@ -50,7 +50,7 @@ export const NOTIFICATION_SEARCH_FILTERS = {
5050
searchDto: SearchRequestDto | InboxRequestDto,
5151
notificationSubRepository: Repository<NotificationSubmission>,
5252
) => {
53-
const formattedSearchString = formatStringToPostgresSearchStringArrayWithWildCard(searchDto.name!);
53+
const formattedSearchString = formatNameSearchString(searchDto.name!);
5454
return notificationSubRepository
5555
.createQueryBuilder('notiSub')
5656
.select('notiSub.fileNumber')
@@ -63,19 +63,19 @@ export const NOTIFICATION_SEARCH_FILTERS = {
6363
new Brackets((qb) =>
6464
qb
6565
.where(
66-
"LOWER(notification_transferee.first_name || ' ' || notification_transferee.last_name) LIKE ANY (:names)",
66+
"LOWER(CONCAT_WS(' ', notification_transferee.first_name, notification_transferee.last_name)) LIKE :name",
6767
{
68-
names: formattedSearchString,
68+
name: formattedSearchString,
6969
},
7070
)
71-
.orWhere('LOWER(notification_transferee.first_name) LIKE ANY (:names)', {
72-
names: formattedSearchString,
71+
.orWhere('LOWER(notification_transferee.first_name) LIKE :name', {
72+
name: formattedSearchString,
7373
})
74-
.orWhere('LOWER(notification_transferee.last_name) LIKE ANY (:names)', {
75-
names: formattedSearchString,
74+
.orWhere('LOWER(notification_transferee.last_name) LIKE :name', {
75+
name: formattedSearchString,
7676
})
77-
.orWhere('LOWER(notification_transferee.organization_name) LIKE ANY (:names)', {
78-
names: formattedSearchString,
77+
.orWhere('LOWER(notification_transferee.organization_name) LIKE :name', {
78+
name: formattedSearchString,
7979
}),
8080
),
8181
)

0 commit comments

Comments
 (0)