使用PG upsert在帖子上创建“喜欢”操作的切换

时间:2018-12-18 06:09:51

标签: postgresql toggle upsert

我正在尝试为帖子创建“赞”功能。 在我的网络应用程序中,我有一个供用户使用的表,一个供发布的表。我创建了一个名为Like_posts的新表,在其中保存了哪个用户喜欢哪个帖子。

一个核心约束,即每个用户只能喜欢一次帖子。如果用户单击他/她已经喜欢的帖子的“喜欢”按钮,则它将切换/删除“喜欢”状态。

基本逻辑是:

如果用户单击“赞”和
  如果like_posts已包含带有user_idpost_id的行,请删除该行(即用户选择不喜欢以前喜欢的帖子), 否则用post_iduser_id添加新行。

目前,我正在触发2个单独的查询,首先要检查该行是否存在,然后我的应用程序决定是否应插入或删除该行。考虑到我希望“喜欢”成为使db数据变异的最常用功能之一,我真的很想在一个查询中做到这一点。

我知道我可以通过数组(posts表中的liked_by-> user_id)做到这一点,但是我不想走这条路。使用不同的数据来展开和重新创建数组不是很有效,我真的不喜欢在PG中使用数组或jsonb(不喜欢API)。

我想使用upsert之类的东西,但是据我所知,我只能执行“冲突时(单列)”,而我需要“冲突时(col1和col2)”。

我有什么选择?怎样在数据库中设计“ Like”按钮的切换?

基于@Laurenz Albe的出色建议,我得以改进该方法。 我现在在2列上有一个唯一的约束,即:

CREATE TABLE LIKE_POSTS (
    POST_ID TEXT NOT NULL,
    USER_ID TEXT NOT NULL,
    CREATED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UPDATED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    DELETED_AT TIMESTAMP,
    CONSTRAINT "Unique_user_and_post_combo" PRIMARY KEY (POST_ID, USER_ID)
);
insert into like_posts (post_id, user_id) values (1,1);

我仍然不确定如何执行删除操作。像这样的东西

insert into like_posts (post_id, user_id) values (1,1) 
returning "ON"
ON CONFLICT ON CONSTRAINT Unique_user_and_post_combo
DO DELETE RETURNING "OFF";

1 个答案:

答案 0 :(得分:1)

现在您已经有了主键约束,切换标记应该很简单:

INSERT INTO like_posts (post_id, user_id, deleted_at)
   VALUES (1, 1, NULL) 
ON CONFLICT ON CONSTRAINT "Unique_user_and_post_combo"
DO UPDATE SET deleted_at = CASE WHEN deleted_at IS NULL
                                THEN current_timestamp
                           END;

这假定您在deleted_at中使用NULL表示该行处于活动状态。

我建议您不要使用大小写混合的名称(就像您对约束所做的那样)。