У меня есть схема, в которой у пользователей есть связанные с ними теги:
user_id: int4 tags: text[]
------------- ------------
1 [ 'apple', 'carrot', 'jelly' ]
2 [ 'jelly', 'zebra' ]
Я ищу создать запрос, который возвращает список всех тегов вместе с их счетчиками. Пример:
tag: text count: int4
--------- -----------
'apple' 1
'carrot' 1
'jelly' 2
'zebra' 1
Триггеры, кажется, идеальный способ сделать это, так как приложение является тяжелым для чтения и легким для записи.
Однако у меня возникают трудности при реализации этого. Сам триггер кажется достаточно простым, я думаю:
CREATE TRIGGER tags_count_update
AFTER UPDATE OF tags ON person
FOR EACH ROW
EXECUTE PROCEDURE trigger_update_tags_count();
trigger_update_tags_count
- это та часть, с которой у меня проблемы, потому что она кажется очень сложной операцией. Например, если тег еще не существует в таблице tags
, он должен быть вставлен со счетом 1.
Кроме того, я считаю, что вам нужно выполнить какую-то операцию сравнения, потому что если чьи-то теги обновляются с [ 'apple', 'carrot', 'jelly' ]
до [ 'apple', 'dogs' ]
, тогда счет apple
не изменяется, carrot
и jelly
уменьшается на 1, а dogs
создается с его счетчиком, установленным на 1. Это усугубляется тем, что теги являются массивами. В настоящее время у меня есть что-то вроде этого:
CREATE OR REPLACE FUNCTION public.trigger_update_tags_count()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
INSERT INTO tags (tag, count) VALUES (new.tag, 1)
ON CONFLICT (tag) DO UPDATE
SET count = CASE WHEN (tag.new AND NOT tag.old) THEN count + 1
WHEN (tag.old AND NOT tag.new) THEN count - 1
ELSE count
END
RETURN NEW;
END;
$function$;
Это немного псевдокод, потому что я не уверен, как интегрировать тот факт, что я имею дело с текстовыми массивами, или как обрабатывать случай сравнения. Спасибо за чтение.