You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断帖子是否被当前用户保存并在前端展示对应状态标识?

两种方案优劣对比

方案一:前端侧ID比对

  • 优势:SQL逻辑简单,帖子列表查询和用户收藏ID查询可以分开做缓存;如果用户收藏量小、分页帖子数少的场景下,前端比对开销几乎可以忽略。
  • 劣势:当用户收藏量达到数千甚至上万级时,接口返回的收藏ID列表体积大,既占用带宽,也会增加前端内存开销;多端适配时还要重复实现比对逻辑,一致性维护成本高。

方案二:数据库子查询判断

  • 优势:逻辑全部收敛在服务端,前端直接拿字段渲染即可,不需要额外处理,不存在收藏量过大的性能问题。
  • 劣势:你当前写的是相关子查询,每返回一条帖子就要执行一次子查询,当分页帖子数较多时查询效率很低;同时你提供的SQL存在语法错误:FROM后缺失表名、users_saved_posts是表名不是字段,无法直接运行。

更优实现方案

1. 优先优化关联表结构

你现在分两张关联表的设计冗余且不必要,用户和帖子的多对多收藏关系,直接用一张中间表就能实现,还能大幅降低查询复杂度:

CREATE TABLE user_saved_posts (
  id INT PRIMARY KEY AUTO_INCREMENT,
  user_id INT NOT NULL REFERENCES users(id),
  post_id INT NOT NULL REFERENCES posts(id),
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  -- 联合唯一索引避免同一用户重复收藏同一帖子
  UNIQUE KEY uk_user_post (user_id, post_id),
  -- 加速关联查询的索引
  INDEX idx_user_id (user_id),
  INDEX idx_post_id (post_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2. 改用LEFT JOIN查询,效率远高于相关子查询

优化后的查询语句,一次联表就能拿到结果,只要索引建对,查询速度和单表查帖子列表基本持平:

SELECT 
  p.*,
  CASE WHEN usp.user_id IS NOT NULL THEN TRUE ELSE FALSE END AS is_post_saved
FROM posts p
LEFT JOIN user_saved_posts usp 
  ON usp.post_id = p.id AND usp.user_id = $1 -- $1替换为当前登录用户的ID
-- 这里加你的分页、筛选条件,比如 LIMIT 10 OFFSET 0

如果暂时不想改动现有表结构,兼容你当前设计的优化查询语句如下:

SELECT 
  p.*,
  CASE WHEN sp.post_id IS NOT NULL THEN TRUE ELSE FALSE END AS is_post_saved
FROM posts p
LEFT JOIN user_saved_posts usp ON usp.user_id = $1
LEFT JOIN saved_post sp ON sp.user_saved_post_id = usp.id AND sp.post_id = p.id

内容的提问来源于stack exchange,提问作者Iskaa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 02:24:04