Postgresql 使用PG upsert为“创建切换”;例如;邮递行动
我正在尝试为帖子创建一个“Like”特性。 在我的web应用程序中,我有一个用户表和一个帖子表。我已经创建了一个名为Postgresql 使用PG upsert为“创建切换”;例如;邮递行动,postgresql,toggle,upsert,Postgresql,Toggle,Upsert,我正在尝试为帖子创建一个“Like”特性。 在我的web应用程序中,我有一个用户表和一个帖子表。我已经创建了一个名为Like_posts的新表,其中保存了哪些用户喜欢哪些帖子 一个核心约束是每个用户只能喜欢一篇文章一次。如果用户点击like按钮查看他/她已经喜欢的帖子,那么它将切换/删除like状态 基本逻辑是: 如果用户单击like和 如果like_posts已经包含一行user_id和post_id,请删除该行(即用户选择不喜欢以前喜欢的帖子), 否则,添加一个带有post\u id和use
Like_posts
的新表,其中保存了哪些用户喜欢哪些帖子
一个核心约束是每个用户只能喜欢一篇文章一次。如果用户点击like按钮查看他/她已经喜欢的帖子,那么它将切换/删除like状态
基本逻辑是:
如果用户单击like和如果
like_posts
已经包含一行user_id
和post_id
,请删除该行(即用户选择不喜欢以前喜欢的帖子),
否则,添加一个带有post\u id
和user\u id
的新行
目前,我正在启动两个独立的查询,首先检查行是否存在,然后我的应用程序决定是否应该插入或删除。考虑到我期望“like”是改变db数据的最常用的特性之一,我真的希望在一个查询中实现它
我知道我可以通过数组(posts表中的用户id
)来完成,但我不想走这条路。使用不同数据展开和重新创建数组的性能不是很好,我真的不喜欢在PG中使用数组或jsonb
(不喜欢API)
我想使用类似于upsert的东西,但据我所知,我只能执行“On Conflict(single column)”,而需要执行“On Conflict(col1和col2)”
我的选项是什么?在我的数据库中设计“Like”按钮切换的好方法是什么
基于@Laurenz Albe的优秀建议,我能够改进这种方法。
我现在在两列上有一个唯一的约束,如下所示:
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";
现在您有了主键约束,切换标志应该很简单:
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_中使用NULL表示该行处于活动状态
我建议您不要使用混合大小写名称(就像您对约束所做的那样)。您可以在两列上使用唯一或主键约束,并且可以在on CONFLICT
子句中使用该约束。这样做的问题是没有其他用户会喜欢该帖子。在我的计划中,这些是有效的行{row1={postid=1,userid=1}},{row2={postid=1,userid=2}}
我看不出问题(postid,userid)
将是表的自然主键。您知道一个主键可以由几列组成,对吗?您也可以有一个int列,单击add1,而update查询有一个returning子句。然后使用mod%2。。。