从零用 Java 实现小红书 SpringBoot Vue UniApp(23)笔记话题多对多:一条笔记进多个话题池

移动端

管理端

前言

早期实现里,一篇笔记只挂一个 topic_id:运营在后台改话题、用户在发现页按话题筛,都够用。但真实社区里常见 同一篇笔记同时出现在「穿搭」和「好物分享」 两个话题池------单字段就卡住了。

在不破坏旧数据的前提下,增加关联表 member_note_topic_rel,主话题仍写 member_note.topic_id(取多选列表第一个),其余话题走关联表;管理端笔记表单支持 多选话题,发现流按关联表过滤。


单话题与多对多对比

维度 单话题字段 多对多
数据模型 member_note.topic_id topic_id + member_note_topic_rel
后台编辑 单选下拉 el-select 多选 topicIds
发现页筛选 WHERE topic_id = ? note_id IN (SELECT ... FROM rel WHERE topic_id = ?)
兼容历史 --- 无 rel 时回退读 topic_id

一、表结构(可重复执行)

脚本:sql/mysql/member_note_topic_rel.sql

  • note_id + topic_id 唯一(含软删)
  • sort:0 表示主话题,与 member_note.topic_id 对齐
  • 初始化 INSERT ... SELECT:把已有笔记的主话题灌进 rel,避免上线后旧笔记「消失」

二、后端:保存时先删后插

管理端保存、App 发布带话题时,统一走 replaceNoteTopics:

复制代码
private void replaceNoteTopics(Long noteId, List<Long> topicIds) {
    memberNoteTopicRelMapper.deleteByNoteId(noteId);
    if (CollUtil.isEmpty(topicIds)) {
        return;
    }
    int sort = 0;
    for (Long topicId : topicIds) {
        memberNoteTopicRelMapper.insert(MemberNoteTopicRelDO.builder()
                .noteId(noteId)
                .topicId(topicId)
                .sort(sort++)
                .build());
    }
}

resolveAdminTopicIds 校验每个话题属于当前频道后,第一个 topicId 写回 member_note.topic_id,保证旧接口、旧报表仍有一个「主话题」字段可读。

读详情时 getNoteTopicIds:优先 rel 列表 ,没有 rel 再降级 note.topicId,H5 不必一次性全量洗数据。


三、发现流 SQL:关联表子查询

MemberNoteMapper 在按话题筛选时,条件从单表字段改为:

复制代码
note_id IN (SELECT note_id FROM member_note_topic_rel
            WHERE deleted = 0 AND topic_id = #{topicId})

同一套逻辑用于关注频道、同城等多场景列表,避免「后台挂了 B 话题、前台只在 A 话题能看到」的割裂。


四、管理端表单:多选 + 校验

管理端 views/member/note/NoteForm.vue

  • 表单项 topicIds:el-select multiple
  • 提交:topicId: topicIds[0],同时传 topicIds 数组
  • 回显:data.topicIds?.length ? data.topicIds : [data.topicId]

运营同学一次勾选多个话题即可,不必复制笔记。


五、App 侧

用户发布笔记时,正文 #话题名 解析仍会自动挂话题;多对多主要在 运营纠偏、活动合集 场景由后台补挂。C 端若只选一个话题,行为与旧版一致。


关键代码位置

模块 路径
DO / Mapper member 模块 MemberNoteTopicRelDO、MemberNoteTopicRelMapper
业务 MemberNoteServiceImpl#replaceNoteTopics、getNoteTopicIds
管理端 VO MemberNoteSaveReqVO.topicIds、MemberNoteRespVO.topicIds
管理端 UI views/member/note/NoteForm.vue

总结

多对多不是「再加一个下拉」,而是 关联表 + 主话题兼容 + 列表 SQL 统一走 rel。这样一条爆款笔记可以同时进多个话题池,后台也不用复制内容。

源码:https://gitee.com/ddeatrr/springboot_vue_xhs

相关推荐
做个文艺程序员4 小时前
MQ第02篇:RabbitMQ快速上手教程:AMQP模型详解+Spring Boot整合实战(附完整代码)
spring boot·消息队列·rabbitmq·java-rabbitmq·amqp
木井巳4 小时前
【BFS 解决拓扑排序】课程表
java·算法·leetcode·广度优先·宽度优先·推荐算法·图搜索算法
RuoyiOffice4 小时前
SpringBoot3 企业定时结算架构:考勤日结、合同到期、库存预警与财务结转如何可靠执行
spring boot·xxl-job·定时任务·分布式任务·spring boot 3·幂等设计·ruoyi office
能源革命4 小时前
Vue 网格拖拽布局组件全景指南:7 大方案深度对比
前端·javascript·vue.js
Crazy________4 小时前
05Linux内存管理核心原理与运维实战
java·开发语言
Nebula_g4 小时前
JavaSE拓展:工具类Executors
java·开发语言·后端·spring·基础·javase
扶风ff5 小时前
练题簿在线免费刷题:会员线下组卷、Word 试卷与成绩导入,课堂检测更方便
java·开发语言·算法·小程序·word
鱼宵5 小时前
Spring AI 可观测与透明化:traceId 串起全链路,思考过程实时直播给用户
java·人工智能·spring·链路追踪·springai
Raas1005 小时前
AI网关能做语义缓存吗?MAI Gateway(魔芋企业级AI网关)实战能力深度解读
java·后端·spring