Skip to content

Commit 7aee92e

Browse files
committed
✨ Sort translations on the main page cards as well
1 parent 15709d1 commit 7aee92e

File tree

2 files changed

+164
-2
lines changed

2 files changed

+164
-2
lines changed
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
CREATE OR REPLACE FUNCTION public.search_jargons(
2+
search_query text DEFAULT NULL::text,
3+
sort_option text DEFAULT 'recent'::text,
4+
limit_count integer DEFAULT 20,
5+
offset_count integer DEFAULT 0,
6+
category_acronyms text[] DEFAULT NULL::text[]
7+
) RETURNS TABLE(
8+
id uuid,
9+
name text,
10+
slug text,
11+
updated_at timestamptz,
12+
translations json,
13+
categories json,
14+
comments json
15+
)
16+
LANGUAGE plpgsql
17+
AS $$
18+
BEGIN
19+
RETURN QUERY
20+
------------------------------------------------------------------
21+
-- Precompute allowed jargons by category filter
22+
------------------------------------------------------------------
23+
WITH allowed_jargon AS (
24+
SELECT j.id
25+
FROM jargon j
26+
WHERE CASE
27+
WHEN category_acronyms IS NULL THEN TRUE
28+
WHEN COALESCE(array_length(category_acronyms, 1), 0) = 0 THEN NOT EXISTS (
29+
SELECT 1 FROM jargon_category jc WHERE jc.jargon_id = j.id
30+
)
31+
ELSE EXISTS (
32+
SELECT 1
33+
FROM jargon_category jc
34+
JOIN category c ON c.id = jc.category_id
35+
WHERE jc.jargon_id = j.id
36+
AND c.acronym = ANY (category_acronyms)
37+
)
38+
END
39+
),
40+
41+
------------------------------------------------------------------
42+
-- 1. jargons matched on their own name
43+
------------------------------------------------------------------
44+
jargon_matches AS (
45+
SELECT
46+
j.id,
47+
j.name,
48+
j.slug,
49+
j.updated_at,
50+
(
51+
SELECT json_agg(
52+
json_build_object('name', t.name)
53+
ORDER BY (t.llm_rank IS NULL), t.llm_rank, t.name
54+
)
55+
FROM translation t
56+
WHERE t.jargon_id = j.id
57+
) AS translations,
58+
(
59+
SELECT json_agg(json_build_object('acronym', c.acronym))
60+
FROM jargon_category jc
61+
JOIN category c ON c.id = jc.category_id
62+
WHERE jc.jargon_id = j.id
63+
) AS categories,
64+
(
65+
SELECT json_build_array(json_build_object('count', COUNT(*)))
66+
FROM comment c
67+
WHERE c.jargon_id = j.id
68+
) AS comments
69+
FROM jargon j
70+
JOIN allowed_jargon aj ON aj.id = j.id
71+
WHERE COALESCE(search_query, '') = ''
72+
OR j.name ILIKE '%' || search_query || '%'
73+
),
74+
75+
------------------------------------------------------------------
76+
-- 2. jargons reached through a translation hit
77+
------------------------------------------------------------------
78+
translation_hits AS (
79+
SELECT DISTINCT j.id
80+
FROM translation t
81+
JOIN jargon j ON j.id = t.jargon_id
82+
JOIN allowed_jargon aj ON aj.id = j.id
83+
WHERE COALESCE(search_query, '') <> ''
84+
AND t.name ILIKE '%' || search_query || '%'
85+
),
86+
translation_matches AS (
87+
SELECT
88+
j.id,
89+
j.name,
90+
j.slug,
91+
j.updated_at,
92+
(
93+
SELECT json_agg(
94+
json_build_object('name', t2.name)
95+
ORDER BY (t2.llm_rank IS NULL), t2.llm_rank, t2.name
96+
)
97+
FROM translation t2
98+
WHERE t2.jargon_id = j.id
99+
) AS translations,
100+
(
101+
SELECT json_agg(json_build_object('acronym', c.acronym))
102+
FROM jargon_category jc
103+
JOIN category c ON c.id = jc.category_id
104+
WHERE jc.jargon_id = j.id
105+
) AS categories,
106+
(
107+
SELECT json_build_array(json_build_object('count', COUNT(*)))
108+
FROM comment c
109+
WHERE c.jargon_id = j.id
110+
) AS comments
111+
FROM translation_hits th
112+
JOIN jargon j ON j.id = th.id
113+
),
114+
115+
------------------------------------------------------------------
116+
-- 3. union + final de-duplication
117+
------------------------------------------------------------------
118+
combined AS (
119+
SELECT * FROM jargon_matches
120+
UNION ALL
121+
SELECT * FROM translation_matches
122+
),
123+
final AS (
124+
SELECT DISTINCT ON (combined.id)
125+
combined.id,
126+
combined.name,
127+
combined.slug,
128+
combined.updated_at,
129+
combined.translations,
130+
combined.categories,
131+
combined.comments
132+
FROM combined
133+
ORDER BY combined.id, combined.updated_at DESC
134+
)
135+
136+
------------------------------------------------------------------
137+
-- 4. paging with dynamic sorting
138+
------------------------------------------------------------------
139+
SELECT
140+
f.id,
141+
f.name,
142+
f.slug,
143+
f.updated_at,
144+
COALESCE(f.translations, '[]'::json) AS translations,
145+
COALESCE(f.categories, '[]'::json) AS categories,
146+
COALESCE(f.comments, '[{"count":0}]'::json) AS comments
147+
FROM final AS f
148+
ORDER BY
149+
CASE WHEN sort_option = 'recent' THEN f.updated_at END DESC,
150+
CASE WHEN sort_option = 'popular' THEN (f.comments->0->>'count')::integer END DESC,
151+
CASE WHEN sort_option = 'abc' THEN f.name END ASC,
152+
CASE WHEN sort_option = 'zyx' THEN f.name END DESC,
153+
f.updated_at DESC,
154+
f.id ASC
155+
LIMIT limit_count
156+
OFFSET offset_count;
157+
END;
158+
$$;
159+
160+
NOTIFY pgrst, 'reload schema';

supabase/seed.sql

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,14 @@ INSERT INTO "public"."jargon_category" ("jargon_id", "category_id") VALUES
2828
('d4ed1ffb-896f-47c5-a94e-0fc7cd7ec1f6', 5);
2929

3030
-- translation
31-
INSERT INTO "public"."translation" ("name", "author_id", "created_at", "updated_at", "id", "jargon_id", "comment_id") VALUES
32-
('테스트 2', 'faa73ac2-bbed-40ea-a392-53baf1a946fe', '2025-08-28 07:19:24.414112+00', '2025-08-28 07:19:24.414112+00', '7b1c9053-d772-4e13-bf43-1940ec66534e', 'fed56078-e4f7-41cf-b608-56fa173a82e6', '02c0cd00-3ccc-444b-bdfb-c7c25b444f7e');
31+
INSERT INTO "public"."translation" ("name", "author_id", "created_at", "updated_at", "id", "jargon_id", "comment_id", "llm_rank") VALUES
32+
('테스트 1', 'faa73ac2-bbed-40ea-a392-53baf1a946fe', '2025-09-27 07:19:24.414112+00', '2025-09-27 07:19:24.414112+00', 'f46ea122-430a-48e1-a343-880af92916c8', 'fed56078-e4f7-41cf-b608-56fa173a82e6', 'ccab4d26-8641-415c-935b-b982e8968951', 1),
33+
('테스트 2', 'faa73ac2-bbed-40ea-a392-53baf1a946fe', '2025-08-28 07:19:24.414112+00', '2025-08-28 07:19:24.414112+00', '7b1c9053-d772-4e13-bf43-1940ec66534e', 'fed56078-e4f7-41cf-b608-56fa173a82e6', '02c0cd00-3ccc-444b-bdfb-c7c25b444f7e', 0);
3334

3435
-- comment
3536
INSERT INTO "public"."comment" ("content", "author_id", "created_at", "updated_at", "removed", "id", "jargon_id", "translation_id", "parent_id") VALUES
3637
('test의 번역이 필요해요.', 'faa73ac2-bbed-40ea-a392-53baf1a946fe', '2025-08-28 07:17:26.730353+00', '2025-08-28 07:17:26.730353+00', false, '31418f6a-fe63-49a8-a8eb-e6205171a4ac', 'd4ed1ffb-896f-47c5-a94e-0fc7cd7ec1f6', NULL, NULL),
3738
('test 2의 번역이 필요해요.', 'faa73ac2-bbed-40ea-a392-53baf1a946fe', '2025-08-28 07:17:41.53785+00', '2025-08-28 07:17:41.53785+00', false, '205e4e38-5fb1-47e0-94b2-8ab2616fcc74', '6af4329d-49e6-4110-8938-f43f3cf30194', NULL, NULL),
3839
('user a test의 번역이 필요해요.', '98e607fc-ef95-4272-9b66-62526b576c84', '2025-08-28 07:17:41.53785+00', '2025-08-28 07:17:41.53785+00', false, '14fe7f09-18d9-4194-a2e1-6ad7e0acea8b', '6af4329d-49e6-4110-8938-f43f3cf30194', NULL, NULL),
40+
('테스트 1을 제안해요.', 'faa73ac2-bbed-40ea-a392-53baf1a946fe', '2025-09-27 07:19:24.414112+00', '2025-09-27 07:19:24.414112+00', false, 'ccab4d26-8641-415c-935b-b982e8968951', 'fed56078-e4f7-41cf-b608-56fa173a82e6', 'f46ea122-430a-48e1-a343-880af92916c8', NULL),
3941
('테스트 2를 제안해요.', 'faa73ac2-bbed-40ea-a392-53baf1a946fe', '2025-08-28 07:19:24.414112+00', '2025-08-28 07:19:24.414112+00', false, '02c0cd00-3ccc-444b-bdfb-c7c25b444f7e', 'fed56078-e4f7-41cf-b608-56fa173a82e6', '7b1c9053-d772-4e13-bf43-1940ec66534e', NULL);

0 commit comments

Comments
 (0)