簡體   English   中英

使用 postgres 觸發器有效地更新標簽計數

[英]Using postgres triggers to update tag counts efficiently

我有一個架構,其中用戶具有與其關聯的標簽:

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表中尚不存在該tags ,則應將其插入,計數為 1。

另外,我相信您需要進行某種差異操作,因為如果某人的標簽從[ 'apple', 'carrot', 'jelly' ][ 'apple', 'dogs' ]那么apple的計數不會不變, carrot and 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$;

這有點偽代碼,因為我不確定如何整合我正在處理文本數組的事實,也不知道如何處理不同的情況。

你在數據中沒有任何叫做tag東西; 它是tags 所以你需要UNNEST()並處理舊標簽和新標簽。 我在想這樣的事情:

INSERT INTO tags (tag, count) 
   SELECT COALESCE(ntag, otag),
          (ntag IS NOT NULL)::int - (otag IS NOT NULL)::int
   FROM UNNEST(new.tags) ntag FULL JOIN
        UNNEST(old.tags) otag
        ON ntag = otag
ON CONFLICT (tag) DO UPDATE
   SET count = count + (excluded.ntag IS NOT NULL)::int - (excluded.otag IS NOT NULL)::int

我不確定您是否需要為此觸發復雜的邏輯。 您可以通過利用Postgres 數組函數unnest()的簡單查詢獲得所需的輸出:

select x.tag, count(*)
from mytable t
cross join lateral unnest(t.tags) x(tag)
group by x.tag

請注意,如果您發現自己重復運行此類查詢,則表明您的設計並不真正適合您的用例; 您最好將每個user_id/tag元組存儲在單獨的表行中,與存儲用戶的表分開。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM