Skip to content

Commit 0b2deaf

Browse files
author
Marcel Mueller
authored
chore: more fuzzy search improvements (#1312)
* chore: more fuzzy search improvements * test: update backend test
1 parent c3b9613 commit 0b2deaf

4 files changed

Lines changed: 28 additions & 5 deletions

File tree

public/backend/src/recreation-resource/utils/buildSearchFilterQuery.spec.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ describe('buildSearchFilterQuery', () => {
1818
const result = buildSearchFilterQuery({ searchText: 'site' });
1919
const queryString = getQueryString(result);
2020
expect(queryString).toBe(
21-
'where display_on_public_site is true and ( name ilike ? or closest_community ilike ? or similarity(name, ?) > 0.3 or similarity(closest_community, ?) > 0.3 or name % ? or closest_community % ? )',
21+
'where display_on_public_site is true and ( name ilike ? or closest_community ilike ? or similarity(name, ?) > 0.3 or similarity(closest_community, ?) > 0.3 or name % ? or closest_community % ? or (length(?) >= 4 and similarity(name, ?) > 0.2) or (length(?) >= 4 and similarity(closest_community, ?) > 0.2) )',
2222
);
2323
expect(result.values).toEqual([
2424
'%site%',
@@ -27,6 +27,10 @@ describe('buildSearchFilterQuery', () => {
2727
'site',
2828
'site',
2929
'site',
30+
'site',
31+
'site',
32+
'site',
33+
'site',
3034
]);
3135
});
3236

@@ -97,7 +101,7 @@ describe('buildSearchFilterQuery', () => {
97101

98102
const queryString = getQueryString(result);
99103
expect(queryString).toContain(
100-
'where display_on_public_site is true and ( name ilike ? or closest_community ilike ? or similarity(name, ?) > 0.3 or similarity(closest_community, ?) > 0.3 or name % ? or closest_community % ? )',
104+
'where display_on_public_site is true and ( name ilike ? or closest_community ilike ? or similarity(name, ?) > 0.3 or similarity(closest_community, ?) > 0.3 or name % ? or closest_community % ? or (length(?) >= 4 and similarity(name, ?) > 0.2) or (length(?) >= 4 and similarity(closest_community, ?) > 0.2) )',
101105
);
102106
expect(queryString).toContain('and access_code in');
103107
expect(queryString).toContain('and district_code in');
@@ -117,6 +121,10 @@ describe('buildSearchFilterQuery', () => {
117121
'site',
118122
'site',
119123
'site',
124+
'site',
125+
'site',
126+
'site',
127+
'site',
120128
'A1',
121129
'A2',
122130
'D1',

public/backend/src/recreation-resource/utils/fuzzySearchUtils.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export const buildFuzzySearchConditions = (searchText: string): Prisma.Sql => {
1616
or similarity(closest_community, ${searchText}) > 0.3
1717
or name % ${searchText}
1818
or closest_community % ${searchText}
19+
or (length(${searchText}) >= 4 and similarity(name, ${searchText}) > 0.2)
20+
or (length(${searchText}) >= 4 and similarity(closest_community, ${searchText}) > 0.2)
1921
)`;
2022
};
2123

@@ -31,7 +33,9 @@ export const buildFuzzySearchScore = (searchText: string): Prisma.Sql => {
3133
similarity(name, ${searchText}),
3234
similarity(closest_community, ${searchText}),
3335
CASE WHEN name % ${searchText} THEN 0.8 ELSE 0 END,
34-
CASE WHEN closest_community % ${searchText} THEN 0.7 ELSE 0 END
36+
CASE WHEN closest_community % ${searchText} THEN 0.7 ELSE 0 END,
37+
CASE WHEN length(${searchText}) >= 4 AND similarity(name, ${searchText}) > 0.2 THEN similarity(name, ${searchText}) ELSE 0 END,
38+
CASE WHEN length(${searchText}) >= 4 AND similarity(closest_community, ${searchText}) > 0.2 THEN similarity(closest_community, ${searchText}) ELSE 0 END
3539
) as fuzzy_score`;
3640
};
3741

public/frontend/src/components/recreation-suggestion-form/utils/fuzzySearch.test.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,14 @@ describe('fuzzySearch', () => {
101101
rank: 12,
102102
option_type: OPTION_TYPE.CITY,
103103
},
104+
{
105+
id: 13,
106+
name: 'Duncan',
107+
latitude: 48.7781,
108+
longitude: -123.7073,
109+
rank: 13,
110+
option_type: OPTION_TYPE.CITY,
111+
},
104112
];
105113

106114
describe('fuzzySearchCities', () => {
@@ -173,7 +181,10 @@ describe('fuzzySearch', () => {
173181
expect(result?.name).toBe(expected);
174182
});
175183

176-
it.each([{ query: 'beach', description: 'does not match "Peachland"' }])(
184+
it.each([
185+
{ query: 'beach', description: 'does not match "Peachland"' },
186+
{ query: 'cabn', description: 'partial single-word query "Duncan"' },
187+
])(
177188
'should NOT match partial single-word names with $description',
178189
({ query }) => {
179190
const result = fuzzySearchBestCity(mockCities, query);

public/frontend/src/components/recreation-suggestion-form/utils/fuzzySearch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const CITY_SUGGESTIONS_OPTIONS: IFuseOptions<City> = {
1111
};
1212

1313
export const BEST_MATCH_CITY_OPTIONS: IFuseOptions<City> = {
14-
threshold: 0.3,
14+
threshold: 0.25,
1515
keys: ['name'],
1616
minMatchCharLength: 3,
1717
includeScore: true,

0 commit comments

Comments
 (0)