Sou muito novo em coisas de banco de dados.
Estou usando o Supabase para criar um aplicativo onde acompanho o número de curtidas em determinados itens ('cliques'). Quero filtrar os itens pela data em que as curtidas foram adicionadas ou por determinadas categorias dos itens. Até agora tenho uma função que posso chamar de javascript como:
const { data, error } = await supabase.rpc('rpc_test', { "json_params": {
"categories": '{"fruits", "test"}',
"start_date": "2024-04-16 00:22:35.837547+00",
} })
Que deve retornar todos os itens que possuem uma categoria correspondente à matriz que passei e o número de cliques que foram criados desde start_date
e antes e end_date
se fornecidos, ou zero se nenhum clique tiver sido criado nessa janela de tempo. E quase funciona, mas continuo encontrando erros que não sei como consertar.
As tabelas importantes em meu banco de dados são:
Unid:
eu ia | nome |
---|---|
1 | maçã |
2 | beterraba |
Cliques:
item_id | criado em |
---|---|
1 | 09/04/2024 |
2 | 09/04/2024 |
Categorias:
eu ia | nome |
---|---|
1 | vegetal |
2 | fruta |
Categorias de itens:
item_id | Categoria ID |
---|---|
1 | 2 |
2 | 1 |
Minha consulta de função atualmente se parece com isto:
create
or replace function public.rpc_test (json_params json default null) returns table (
id bigint,
created_at timestamp with time zone,
name text,
clicks bigint,
categories_arr text[]
) as $$
BEGIN
RETURN QUERY
select
items.id,
items.created_at,
items.name,
click_counts.clicks,
item_id_to_cat_array.categories_arr
from
items
LEFT JOIN (
SELECT item_categories.item_id AS itemid, array_agg(categories.name) AS categories_arr
FROM item_categories
JOIN categories ON categories.id = item_categories.category_id
GROUP BY item_categories.item_id
) item_id_to_cat_array ON items.id = item_id_to_cat_array.itemid
LEFT JOIN (
SELECT item_id as click_item_id, count(c.id) AS clicks
FROM clicks as c
WHERE (json_params->>'start_date' IS NULL OR c.created_at >= (json_params->>'start_date')::date)
AND (json_params->>'end_date' IS NULL OR c.created_at <= (json_params->>'end_date')::date)
GROUP BY c.item_id
) click_counts ON click_item_id = items.id
where
json_params->>'categories' IS NULL OR
(json_params->>'categories')::text[] && item_id_to_cat_array.categories_arr;
END;
$$ language plpgsql;
O único problema com isso é que categories_arr
nunca há dados.
Em vários pontos, tive iterações disso que funcionaram para coletar as informações que desejo, mas sem a filtragem implementada. Tentei fazer coisas com GROUP BY e HAVING e não tenho certeza de para onde ir.
Como posso obter mais informações sobre o que está acontecendo na minha consulta?
Gostaria de ver o categories_arr
que está acontecendo em cada etapa do processo, mas não sei como registrar essas informações.
Não é simples monitorar as etapas de uma consulta SQL durante a execução. SQL é uma linguagem declarativa . Você parece pensar processualmente. Em um bloco de código PL/pgSQL real, você pode gerar qualquer coisa entre
RAISE NOTICE
as etapas. Existem até depuradores, como aquele embutido no pgAdmin - que quase nunca uso.Mas sua função é apenas um wrapper em torno de uma grande consulta SQL. Então isso não lhe daria nada.
Assumindo um design padrão muitos para muitos como:
Depois de mudar para simpler
LANGUAGE sql
, sua função poderia ficar assim:Você teve vários problemas de SQL. Reescrevi a lógica para fazê-la funcionar.
item_categories.item_id
é o suficiente por enquanto.items
para obter detalhes do item.Observe que isso espera entrada para
_categories
, pois a consulta não seria boa para retornar todos os itens. Se você precisar dessa opção, volteLANGUAGE plpgsql
e bifurque o caso com uma consulta separada.