From 750166eecdc206df7dced71f3e2ec7e71866c329 Mon Sep 17 00:00:00 2001 From: Hung Ta Date: Fri, 22 Nov 2024 12:16:56 +0700 Subject: [PATCH 1/4] SQL --- .../database/sql/comment_count_migration.sql | 7 +++ .../sql/get_filtering_options_function.sql | 14 ++++-- .../database/sql/get_snippets_function.sql | 48 +++++++++++++------ .../database/sql/like_count_migration.sql | 9 ++++ supabase/database/sql/like_count_trigger.sql | 4 ++ .../sql/update_snippet_comment_count.sql | 19 ++++++++ .../sql/update_snippet_like_count.sql | 16 +++++++ .../sql/update_snippet_upvote_count.sql | 25 ++++++++++ 8 files changed, 124 insertions(+), 18 deletions(-) create mode 100644 supabase/database/sql/comment_count_migration.sql create mode 100644 supabase/database/sql/like_count_migration.sql create mode 100644 supabase/database/sql/like_count_trigger.sql create mode 100644 supabase/database/sql/update_snippet_comment_count.sql create mode 100644 supabase/database/sql/update_snippet_like_count.sql create mode 100644 supabase/database/sql/update_snippet_upvote_count.sql diff --git a/supabase/database/sql/comment_count_migration.sql b/supabase/database/sql/comment_count_migration.sql new file mode 100644 index 0000000..1529ce2 --- /dev/null +++ b/supabase/database/sql/comment_count_migration.sql @@ -0,0 +1,7 @@ +UPDATE snippets s +SET comment_count = ( + SELECT COUNT(*) + FROM comments c + WHERE c.room_id = s.id + and deleted_at is null +); diff --git a/supabase/database/sql/get_filtering_options_function.sql b/supabase/database/sql/get_filtering_options_function.sql index 8a4cfd5..f0cd1ac 100644 --- a/supabase/database/sql/get_filtering_options_function.sql +++ b/supabase/database/sql/get_filtering_options_function.sql @@ -68,13 +68,19 @@ BEGIN -- Fetch unique radio station codes from the audio_files table WITH unique_sources AS ( - SELECT DISTINCT radio_station_code - FROM public.audio_files - WHERE radio_station_code IS NOT NULL + SELECT DISTINCT + radio_station_code, + radio_station_name + FROM public.audio_files + WHERE radio_station_code IS NOT NULL ) SELECT jsonb_agg( jsonb_build_object( - 'label', radio_station_code, + 'label', CASE + WHEN radio_station_name IS NOT NULL + THEN radio_station_name || ' - ' || radio_station_code + ELSE radio_station_code + END, 'value', radio_station_code ) ) INTO sources diff --git a/supabase/database/sql/get_snippets_function.sql b/supabase/database/sql/get_snippets_function.sql index 1a07996..de9601b 100644 --- a/supabase/database/sql/get_snippets_function.sql +++ b/supabase/database/sql/get_snippets_function.sql @@ -3,8 +3,10 @@ OR REPLACE FUNCTION get_snippets ( page INTEGER DEFAULT 0, page_size INTEGER DEFAULT 10, p_language TEXT DEFAULT 'english', - p_filter JSONB DEFAULT '{}'::jsonb + p_filter JSONB DEFAULT '{}'::jsonb, + p_order_by TEXT DEFAULT 'recorded_at_desc' ) RETURNS jsonb SECURITY DEFINER AS $$ + DECLARE current_user_id UUID; result jsonb; @@ -23,7 +25,7 @@ BEGIN SELECT array_agg(r.name) INTO user_roles FROM public.user_roles ur JOIN public.roles r ON ur.role = r.id - WHERE ur."user" = current_user_id; + WHERE ur."user" = current_user_id; -- Check if the current user has the 'admin' role user_is_admin := COALESCE('admin' = ANY(user_roles), FALSE); @@ -75,20 +77,20 @@ BEGIN LEFT JOIN user_like_snippets ul ON ul.snippet = s.id AND ul."user" = current_user_id LEFT JOIN user_hide_snippets uhs ON uhs.snippet = s.id CROSS JOIN LATERAL ( - SELECT + SELECT COUNT(*) FILTER (WHERE value = 1) AS likes, COUNT(*) FILTER (WHERE value = -1) AS dislikes - FROM user_like_snippets uls + FROM user_like_snippets uls WHERE uls.snippet = s.id ) like_counts WHERE s.status = 'Processed' AND (s.confidence_scores->>'overall')::INTEGER >= 95 AND ( -- If user is admin, show all snippets (including hidden ones) -- If user is not admin, only show non-hidden snippets - user_is_admin OR + user_is_admin OR NOT EXISTS ( - SELECT 1 - FROM user_hide_snippets uhs + SELECT 1 + FROM user_hide_snippets uhs WHERE uhs.snippet = s.id ) ) @@ -214,7 +216,25 @@ BEGIN ) ) ) - ORDER BY s.recorded_at DESC; + ORDER BY + CASE + WHEN p_order_by = 'upvotes' THEN (s.upvote_count + s.like_count) + ELSE NULL + END DESC NULLS LAST, + CASE + WHEN p_order_by = 'comments' THEN s.comment_count + ELSE NULL + END DESC NULLS LAST, + CASE + WHEN p_order_by = 'activities' THEN s.updated_at + ELSE NULL + END DESC NULLS LAST, + CASE + WHEN p_order_by IS NULL OR p_order_by = 'latest' OR p_order_by = '' THEN s.recorded_at + ELSE NULL + END DESC NULLS LAST, + -- Default fallback to recorded_at if no other conditions match + s.recorded_at DESC NULLS LAST; -- Get total count SELECT COUNT(*) INTO total_count @@ -235,11 +255,11 @@ BEGIN total_pages := CEIL(total_count::FLOAT / page_size); RETURN jsonb_build_object( - 'num_of_snippets', COALESCE(jsonb_array_length(result), 0), - 'snippets', COALESCE(result, '[]'::jsonb), - 'current_page', page, - 'page_size', page_size, - 'total_pages', total_pages - ); + 'num_of_snippets', total_count, + 'snippets', COALESCE(result, '[]'::jsonb), + 'current_page', page, + 'page_size', page_size, + 'total_pages', total_pages +); END; $$ LANGUAGE plpgsql; diff --git a/supabase/database/sql/like_count_migration.sql b/supabase/database/sql/like_count_migration.sql new file mode 100644 index 0000000..7cbab37 --- /dev/null +++ b/supabase/database/sql/like_count_migration.sql @@ -0,0 +1,9 @@ +UPDATE snippets s +SET like_count = ( + SELECT COUNT(*) + FROM user_like_snippets uls + WHERE uls.snippet = s.id + AND uls.value = 1 +); + +CREATE INDEX idx_snippets_like_count ON snippets(like_count DESC); diff --git a/supabase/database/sql/like_count_trigger.sql b/supabase/database/sql/like_count_trigger.sql new file mode 100644 index 0000000..1eedfde --- /dev/null +++ b/supabase/database/sql/like_count_trigger.sql @@ -0,0 +1,4 @@ +CREATE TRIGGER update_like_count +AFTER INSERT OR UPDATE OR DELETE ON user_like_snippets +FOR EACH ROW +EXECUTE FUNCTION update_snippet_like_count(); diff --git a/supabase/database/sql/update_snippet_comment_count.sql b/supabase/database/sql/update_snippet_comment_count.sql new file mode 100644 index 0000000..43011ba --- /dev/null +++ b/supabase/database/sql/update_snippet_comment_count.sql @@ -0,0 +1,19 @@ +CREATE OR REPLACE FUNCTION update_snippet_comment_count() +RETURNS TRIGGER AS $$ +BEGIN + -- For INSERT + IF (TG_OP = 'INSERT') THEN + UPDATE snippets + SET comment_count = comment_count + 1 + WHERE id = NEW.room_id; + + -- For DELETE + ELSIF (TG_OP = 'DELETE') THEN + UPDATE snippets + SET comment_count = comment_count - 1 + WHERE id = OLD.room_id; + END IF; + + RETURN NULL; +END; +$$ LANGUAGE plpgsql; diff --git a/supabase/database/sql/update_snippet_like_count.sql b/supabase/database/sql/update_snippet_like_count.sql new file mode 100644 index 0000000..a753b62 --- /dev/null +++ b/supabase/database/sql/update_snippet_like_count.sql @@ -0,0 +1,16 @@ +CREATE OR REPLACE FUNCTION update_snippet_like_count() +RETURNS TRIGGER AS $$ +BEGIN + -- Update the like count for the affected snippet + UPDATE snippets + SET like_count = ( + SELECT COUNT(*) + FROM user_like_snippets + WHERE snippet = COALESCE(NEW.snippet, OLD.snippet) + AND value = 1 + ) + WHERE id = COALESCE(NEW.snippet, OLD.snippet); + + RETURN NULL; +END; +$$ LANGUAGE plpgsql; diff --git a/supabase/database/sql/update_snippet_upvote_count.sql b/supabase/database/sql/update_snippet_upvote_count.sql new file mode 100644 index 0000000..ca7934c --- /dev/null +++ b/supabase/database/sql/update_snippet_upvote_count.sql @@ -0,0 +1,25 @@ +CREATE OR REPLACE FUNCTION update_snippet_upvote_count() +RETURNS TRIGGER AS $$ +DECLARE + snippet_id UUID; +BEGIN + -- Get the snippet_id from snippet_labels + SELECT snippet INTO snippet_id + FROM snippet_labels + WHERE id = COALESCE(NEW.snippet_label, OLD.snippet_label); + + -- Update the upvote count for the affected snippet + IF snippet_id IS NOT NULL THEN + UPDATE snippets + SET upvote_count = ( + SELECT COUNT(*) + FROM label_upvotes lu + JOIN snippet_labels sl ON lu.snippet_label = sl.id + WHERE sl.snippet = snippet_id + ) + WHERE id = snippet_id; + END IF; + + RETURN NULL; +END; +$$ LANGUAGE plpgsql; From 67932dc4562d30303a68d88ad2dc313030a78dd7 Mon Sep 17 00:00:00 2001 From: Hung Ta Date: Fri, 22 Nov 2024 15:32:35 +0700 Subject: [PATCH 2/4] [f] Add upvote filter --- .../database/sql/get_snippets_function.sql | 52 ++++++++++++++++--- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/supabase/database/sql/get_snippets_function.sql b/supabase/database/sql/get_snippets_function.sql index de9601b..437f934 100644 --- a/supabase/database/sql/get_snippets_function.sql +++ b/supabase/database/sql/get_snippets_function.sql @@ -1,12 +1,5 @@ CREATE -OR REPLACE FUNCTION get_snippets ( - page INTEGER DEFAULT 0, - page_size INTEGER DEFAULT 10, - p_language TEXT DEFAULT 'english', - p_filter JSONB DEFAULT '{}'::jsonb, - p_order_by TEXT DEFAULT 'recorded_at_desc' -) RETURNS jsonb SECURITY DEFINER AS $$ - +OR REPLACE FUNCTION get_snippets_order_by (p_language text,p_filter jsonb,page INTEGER,page_size INTEGER, p_order_by text) RETURNS jsonb SECURITY DEFINER AS $$ DECLARE current_user_id UUID; result jsonb; @@ -216,6 +209,49 @@ BEGIN ) ) ) + AND ( + p_filter IS NULL OR + NOT p_filter ? 'upvotedBy' OR + ( + CASE + WHEN jsonb_array_length(p_filter->'upvotedBy') = 0 THEN TRUE + ELSE ( + CASE + WHEN ( + p_filter->'upvotedBy' ? 'by_me' AND + p_filter->'upvotedBy' ? 'by_others' + ) THEN + EXISTS ( + SELECT 1 + FROM label_upvotes lu + WHERE lu.snippet_label IN ( + SELECT id FROM snippet_labels WHERE snippet = s.id + ) + ) + WHEN p_filter->'upvotedBy' ? 'by_me' THEN + EXISTS ( + SELECT 1 + FROM label_upvotes lu + WHERE lu.snippet_label IN ( + SELECT id FROM snippet_labels WHERE snippet = s.id + ) + AND lu.upvoted_by = current_user_id + ) + WHEN p_filter->'upvotedBy' ? 'by_others' THEN + EXISTS ( + SELECT 1 + FROM label_upvotes lu + WHERE lu.snippet_label IN ( + SELECT id FROM snippet_labels WHERE snippet = s.id + ) + AND lu.upvoted_by != current_user_id + ) + ELSE FALSE + END + ) + END + ) + ) ORDER BY CASE WHEN p_order_by = 'upvotes' THEN (s.upvote_count + s.like_count) From f337a0efca09306c6fe1fc5136bf7973c9da5999 Mon Sep 17 00:00:00 2001 From: Hung Ta Date: Mon, 25 Nov 2024 15:11:02 +0700 Subject: [PATCH 3/4] [f] Update based on comments --- .../database/sql/comment_count_migration.sql | 2 ++ .../sql/update_snippet_comment_count.sql | 21 +++++++------------ .../database/sql/upvote_count_migration.sql | 13 ++++++++++++ 3 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 supabase/database/sql/upvote_count_migration.sql diff --git a/supabase/database/sql/comment_count_migration.sql b/supabase/database/sql/comment_count_migration.sql index 1529ce2..3dc05a2 100644 --- a/supabase/database/sql/comment_count_migration.sql +++ b/supabase/database/sql/comment_count_migration.sql @@ -5,3 +5,5 @@ SET comment_count = ( WHERE c.room_id = s.id and deleted_at is null ); + +CREATE INDEX idx_snippets_comment_count ON snippets(comment_count DESC); diff --git a/supabase/database/sql/update_snippet_comment_count.sql b/supabase/database/sql/update_snippet_comment_count.sql index 43011ba..3ad5189 100644 --- a/supabase/database/sql/update_snippet_comment_count.sql +++ b/supabase/database/sql/update_snippet_comment_count.sql @@ -1,18 +1,13 @@ -CREATE OR REPLACE FUNCTION update_snippet_comment_count() +CREATE OR REPLACE FUNCTION update_snippet_comment_count() RETURNS TRIGGER AS $$ BEGIN - -- For INSERT - IF (TG_OP = 'INSERT') THEN - UPDATE snippets - SET comment_count = comment_count + 1 - WHERE id = NEW.room_id; - - -- For DELETE - ELSIF (TG_OP = 'DELETE') THEN - UPDATE snippets - SET comment_count = comment_count - 1 - WHERE id = OLD.room_id; - END IF; + UPDATE snippets + SET comment_count = ( + SELECT COUNT(*) + FROM comments + WHERE room_id = COALESCE(NEW.room_id, OLD.room_id) + ) + WHERE id = COALESCE(NEW.room_id, OLD.room_id); RETURN NULL; END; diff --git a/supabase/database/sql/upvote_count_migration.sql b/supabase/database/sql/upvote_count_migration.sql new file mode 100644 index 0000000..1c761f8 --- /dev/null +++ b/supabase/database/sql/upvote_count_migration.sql @@ -0,0 +1,13 @@ +WITH upvote_counts AS ( + SELECT sl.snippet AS snippet_id, + COUNT(lu.id) AS total_upvotes + FROM snippet_labels sl + LEFT JOIN label_upvotes lu ON lu.snippet_label = sl.id + GROUP BY sl.snippet +) +UPDATE snippets s +SET upvote_count = COALESCE(uc.total_upvotes, 0) +FROM upvote_counts uc +WHERE s.id = uc.snippet_id; + +CREATE INDEX idx_snippets_upvote_count ON snippets(upvote_count DESC); From 1f43bb9701b453850af11dea63aec6c74b416017 Mon Sep 17 00:00:00 2001 From: Phong Nguyen Date: Mon, 25 Nov 2024 15:42:10 +0700 Subject: [PATCH 4/4] Fix the get_snippets function --- .../database/sql/get_snippets_function.sql | 64 +++++++++++-------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/supabase/database/sql/get_snippets_function.sql b/supabase/database/sql/get_snippets_function.sql index 4f5a2e6..3db5590 100644 --- a/supabase/database/sql/get_snippets_function.sql +++ b/supabase/database/sql/get_snippets_function.sql @@ -1,5 +1,5 @@ CREATE -OR REPLACE FUNCTION get_snippets_order_by (p_language text,p_filter jsonb,page INTEGER,page_size INTEGER, p_order_by text) RETURNS jsonb SECURITY DEFINER AS $$ +OR REPLACE FUNCTION get_snippets (p_language text,p_filter jsonb,page INTEGER,page_size INTEGER, p_order_by text) RETURNS jsonb SECURITY DEFINER AS $$ DECLARE current_user_id UUID; result jsonb; @@ -18,7 +18,7 @@ BEGIN SELECT array_agg(r.name) INTO user_roles FROM public.user_roles ur JOIN public.roles r ON ur.role = r.id - WHERE ur."user" = current_user_id; + WHERE ur."user" = current_user_id; -- Check if the current user has the 'admin' role user_is_admin := COALESCE('admin' = ANY(user_roles), FALSE); @@ -70,20 +70,20 @@ BEGIN LEFT JOIN user_like_snippets ul ON ul.snippet = s.id AND ul."user" = current_user_id LEFT JOIN user_hide_snippets uhs ON uhs.snippet = s.id CROSS JOIN LATERAL ( - SELECT + SELECT COUNT(*) FILTER (WHERE value = 1) AS likes, COUNT(*) FILTER (WHERE value = -1) AS dislikes - FROM user_like_snippets uls + FROM user_like_snippets uls WHERE uls.snippet = s.id ) like_counts WHERE s.status = 'Processed' AND (s.confidence_scores->>'overall')::INTEGER >= 95 AND ( -- If user is admin, show all snippets (including hidden ones) -- If user is not admin, only show non-hidden snippets - user_is_admin OR + user_is_admin OR NOT EXISTS ( - SELECT 1 - FROM user_hide_snippets uhs + SELECT 1 + FROM user_hide_snippets uhs WHERE uhs.snippet = s.id ) ) @@ -252,8 +252,8 @@ BEGIN END ) ) - AND - NOT EXISTS ( + AND ( + NOT EXISTS ( SELECT 1 FROM ( SELECT snippet @@ -264,25 +264,33 @@ BEGIN ) dislikes WHERE dislikes.snippet = s.id ) - ORDER BY - CASE - WHEN p_order_by = 'upvotes' THEN (s.upvote_count + s.like_count) - ELSE NULL - END DESC NULLS LAST, - CASE - WHEN p_order_by = 'comments' THEN s.comment_count - ELSE NULL - END DESC NULLS LAST, - CASE - WHEN p_order_by = 'activities' THEN s.updated_at - ELSE NULL - END DESC NULLS LAST, - CASE - WHEN p_order_by IS NULL OR p_order_by = 'latest' OR p_order_by = '' THEN s.recorded_at - ELSE NULL - END DESC NULLS LAST, - -- Default fallback to recorded_at if no other conditions match - s.recorded_at DESC NULLS LAST; + ) + ORDER BY ( + -- Sort by engagement (upvotes + likes) + CASE WHEN p_order_by = 'upvotes' + THEN s.upvote_count + s.like_count + END DESC, + + -- Sort by comment count + CASE WHEN p_order_by = 'comments' + THEN s.comment_count + END DESC, + + -- Sort by last activity date + CASE WHEN p_order_by = 'activities' + THEN s.updated_at + END DESC, + + -- Sort by recording date (default sort) + CASE WHEN p_order_by IS NULL OR + p_order_by = 'latest' OR + p_order_by = '' + THEN s.recorded_at + END DESC, + + -- Always sort by recorded_at as final tiebreaker + s.recorded_at DESC; + ) -- Get total count SELECT COUNT(*) INTO total_count