繁体   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