从零用 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

相关推荐
niucloud-admin17 分钟前
NIUCLOUD PHP SAAS上门家政使用文档:服务保障
java·开发语言·php
IT枫斗者枫哥30 分钟前
CompletableFuture失败后返回空列表:异常没了,业务含义也变了
java·后端
知识搬运临时工41 分钟前
一个模板把 AEM 拖进 Full GC 死亡螺旋:300% CPU、7 GB 堆、310 万行堆栈
java·aws
用户432935928051 小时前
CoAP还是MQTT:1万只Cat.1水表三个月带宽续航实测
java
小大宇1 小时前
Vue知识点-ElementPlus-06 单选+多选+下拉+日期选择
前端·vue.js·elementui
知守观1 小时前
多模块架构演进:横向分层 vs 纵向领域,13 个真实项目的切分对照
java·后端·微服务
Java成神之路-1 小时前
Java String 为什么不可变?和 HashMap 到底有什么关系?
java
paopaokaka_luck1 小时前
基于springboot+vue的益暖微光公益服务平台(DeepSeek公益助手、善款信息追溯、志愿服务积分闭环、ECharts运营分析、活动状态自动流转)
java·前端·javascript·spring boot·mysql·架构·echarts
文丑颜不良啊1 小时前
LeetCode1401~1420题目解析
java·leetcode
Nuanyt1 小时前
LeetCode Hot 100 链表专题2 3 题 (Java)
java·笔记·算法·leetcode·链表