Use full text search instead of ilike for search functionality

This commit is contained in:
thiloho
2024-08-14 21:37:19 +02:00
parent 0e3fb96dda
commit 3eb05da564
5 changed files with 90 additions and 4 deletions

View File

@@ -11,7 +11,7 @@ DECLARE
_allowed_mimetypes TEXT[] := ARRAY['image/png', 'image/svg+xml', 'image/jpeg', 'image/webp']; _allowed_mimetypes TEXT[] := ARRAY['image/png', 'image/svg+xml', 'image/jpeg', 'image/webp'];
_max_file_size INT := 5 * 1024 * 1024; _max_file_size INT := 5 * 1024 * 1024;
BEGIN BEGIN
IF octet_length($1) = 0 THEN IF OCTET_LENGTH($1) = 0 THEN
RAISE invalid_parameter_value RAISE invalid_parameter_value
USING message = 'No file data was provided'; USING message = 'No file data was provided';
END IF; END IF;

View File

@@ -0,0 +1,86 @@
-- migrate:up
ALTER TABLE internal.website
ADD COLUMN title_search TSVECTOR GENERATED ALWAYS AS (TO_TSVECTOR('english', title)) STORED;
CREATE OR REPLACE VIEW api.website WITH ( security_invoker = ON
) AS
SELECT
id,
user_id,
content_type,
title,
created_at,
last_modified_at,
last_modified_by,
title_search -- New column
FROM
internal.website;
GRANT SELECT, UPDATE, DELETE ON api.website TO authenticated_user;
ALTER TABLE internal.article
ADD COLUMN title_description_search TSVECTOR GENERATED ALWAYS AS (TO_TSVECTOR('english', COALESCE(title, '') || ' ' || COALESCE(meta_description, ''))) STORED;
CREATE OR REPLACE VIEW api.article WITH ( security_invoker = ON
) AS
SELECT
id,
website_id,
user_id,
title,
meta_description,
meta_author,
cover_image,
publication_date,
main_content,
created_at,
last_modified_at,
last_modified_by,
title_description_search -- New column
FROM
internal.article;
GRANT SELECT, INSERT, UPDATE, DELETE ON api.article TO authenticated_user;
-- migrate:down
DROP VIEW api.article;
CREATE VIEW api.article WITH ( security_invoker = ON
) AS
SELECT
id,
website_id,
user_id,
title,
meta_description,
meta_author,
cover_image,
publication_date,
main_content,
created_at,
last_modified_at,
last_modified_by
FROM
internal.article;
ALTER TABLE internal.article
DROP COLUMN title_description_search;
DROP VIEW api.website;
CREATE VIEW api.website WITH ( security_invoker = ON
) AS
SELECT
id,
user_id,
content_type,
title,
created_at,
last_modified_at,
last_modified_by
FROM
internal.website;
ALTER TABLE internal.website
DROP COLUMN title_search;

View File

@@ -10,7 +10,7 @@ export const load: PageServerLoad = async ({ fetch, cookies, url }) => {
const baseFetchUrl = `${API_BASE_PREFIX}/website`; const baseFetchUrl = `${API_BASE_PREFIX}/website`;
if (searchQuery) { if (searchQuery) {
params.append("title", `ilike.*${searchQuery}*`); params.append("title_search", `wfts(english).${searchQuery}`);
} }
switch (sortBy) { switch (sortBy) {

View File

@@ -10,7 +10,7 @@ export const load: PageServerLoad = async ({ params, fetch, cookies, url, parent
const baseFetchUrl = `${API_BASE_PREFIX}/article?website_id=eq.${params.websiteId}&select=id,title`; const baseFetchUrl = `${API_BASE_PREFIX}/article?website_id=eq.${params.websiteId}&select=id,title`;
if (searchQuery) { if (searchQuery) {
parameters.append("title", `ilike.*${searchQuery}*`); parameters.append("title_description_search", `wfts(english).${searchQuery}`);
} }
switch (sortBy) { switch (sortBy) {

View File

@@ -18,7 +18,7 @@ export const load: PageServerLoad = async ({ parent, params, cookies, fetch }) =
}; };
export const actions: Actions = { export const actions: Actions = {
default: async ({ fetch, cookies, request, params, locals }) => { default: async ({ fetch, cookies, request, params }) => {
const data = await request.formData(); const data = await request.formData();
const coverFile = data.get("cover-image") as File; const coverFile = data.get("cover-image") as File;