🎓 一、 选题背景:为什么选这个题?
兄弟们,如果你还在做普通的《校园二手交易平台》,那你大概率只能拿个及格分。为什么?因为闲鱼、转转已经把这个模式做烂了,导师会觉得你只是个CRUD 搬运工。
但是!只要我们在标题里加上“智能推荐”或“协同过滤算法”这几个字,逼格瞬间起飞:
- 技术降维打击:别的同学在讲“怎么增删改查”,你在讲“基于用户行为矩阵的推荐算法”,这就像拿着加特林去打冷兵器战争。
- 解决痛点:解决了二手交易中“东西太多找不到”和“不知道买啥”的痛点,逻辑满分。
- 实现极简:所谓的“算法”,其实就是一条SQL 语句(买了A的人也买了B)。
🏗️ 二、 系统架构设计
为了撑起论文的字数,架构图必须画得像那么回事。我们采用推荐引擎 + 业务系统双核心架构。
1. 技术栈选型
- 后端:Spring Boot 2.7+、MyBatis Plus
- 前端:Vue 3 + Element Plus
- 算法核心:SQL (Item-CF 核心逻辑 implementation)
- 数据库:MySQL 8.0
- 加分项:Redis (缓存热门推荐列表)
2. 系统逻辑架构图 (Mermaid)
这张图的精髓在于把简单的查询包装成了“推荐引擎”。
🛠️ 三、 核心数据库设计
实现协同过滤,我们不需要复杂的 Python 库,只需要两张表:图书表和订单详情表(或者收藏表)。
1. 订单详情表 (sys_order_item)
这张表是算法的数据源。它记录了“谁”买了“什么”。
| 字段名 | 类型 | 说明 | 备注 |
|---|---|---|---|
id | BIGINT | 主键 | - |
user_id | BIGINT | 用户ID | 谁买的 |
book_id | BIGINT | 图书ID | 买了什么 |
category_id | INT | 分类ID | 兜底推荐用 |
create_time | DATETIME | 下单时间 | - |
2. 图书信息表 (sys_book)
| 字段名 | 类型 | 说明 | 备注 |
|---|---|---|---|
book_id | BIGINT | 主键 | - |
title | VARCHAR | 书名 | - |
author | VARCHAR | 作者 | - |
category_id | INT | 分类ID | 计算机/文学/教材 |
💻 四、 核心功能实现(算法解密)
这里我们实现一个经典的基于物品的协同过滤 (Item-Based CF)的简化版。
核心逻辑:“喜欢物品 A 的用户,同时也喜欢物品 B”。
转化成 SQL:找到所有买了“当前这本书”的用户,再看看这些用户还买了“哪些其他书”,按出现次数排序。
1. 算法核心 Service (RecommendService.java)
@ServicepublicclassRecommendService{@AutowiredprivateOrderItemMapperorderItemMapper;@AutowiredprivateBookMapperbookMapper;/** * 核心推荐算法接口 * @param bookId 当前用户正在看的书ID * @return 推荐的书籍列表 */publicList<Book>getRecommendations(LongbookId){// 1. 协同过滤推荐 (Item-CF)// 逻辑:找出买了 bookId 的人,还买了啥?List<Long>recommendedBookIds=orderItemMapper.selectCoOccurringBooks(bookId);// 2. 冷启动兜底方案 (Cold Start)// 如果没人买过这本书,算法查不到数据,就退化为"同类目推荐"if(recommendedBookIds.isEmpty()){BookcurrentBook=bookMapper.selectById(bookId);returnbookMapper.selectList(newQueryWrapper<Book>().eq("category_id",currentBook.getCategoryId()).ne("book_id",bookId)// 排除自己.last("LIMIT 5"));// 取前5本}// 3. 根据ID查详情returnbookMapper.selectBatchIds(recommendedBookIds);}}2. 核心 SQL 写法 (OrderItemMapper.xml)
这就是价值 100 分的 SQL 语句。它完成了数据挖掘工程师的工作。
<selectid="selectCoOccurringBooks"resultType="java.lang.Long">SELECT t2.book_id FROM sys_order_item t1 JOIN sys_order_item t2 ON t1.user_id = t2.user_id -- 同一个用户 WHERE t1.book_id = #{bookId} -- 买了当前这本书 AND t2.book_id != #{bookId} -- 排除当前这本书自己 GROUP BY t2.book_id -- 按其他书分组 ORDER BY COUNT(t2.book_id) DESC -- 按共现次数倒序(买的人越多越靠前) LIMIT 5 -- 只推荐前5本</select>📸 五、 运行效果展示 (答辩 PPT 素材)
答辩时,你不需要展示后台代码,要展示前台的“智能”。
- 书籍详情页:
- 左边展示《Java编程思想》。
- 右侧侧边栏:标题叫“猜你喜欢”或者“购买此书的同学也买了”。
- 内容:展示算法推出来的《深入理解JVM》、《高性能MySQL》。
- 话术:“老师,这里不是乱推的,是根据全校同学的真实交易数据计算出来的关联度。”
- 首页“千人千面”:
- 如果用户登录了,根据他最近浏览的分类,展示相关推荐。
- 如果没登录,展示“全站热销榜”(简单的
ORDER BY sales DESC)。
🗣️ 六、 答辩高分话术(防御术)
老师一看到“算法”,肯定会产生兴趣(或者质疑),你要准备好这套说辞:
Q1: 你的协同过滤算法数据量够吗?会有冷启动问题吗?
A (高情商版):"老师,您问到了点子上。协同过滤确实强依赖历史数据。为了解决**‘冷启动’(Cold Start)** 问题,我设计了一套混合推荐策略:
- 当一本书有足够的交易记录时,我使用Item-CF算法,推荐准确度高。
- 当这是一本新上架的书(无交易记录)时,系统会自动降级为基于内容的推荐 (Content-Based),也就是推荐同分类下的热门书籍。
这样保证了无论数据多少,用户体验都是流畅的。"
Q2: 为什么用 SQL 做算法?性能跟得上吗?
A (务实版):“在校园二手书这个场景下,图书数量通常在万级以内。MySQL 对于百万级数据的 Join 和 Group By 操作是非常高效的,能在毫秒级返回结果。而且,为了进一步提升性能,我可以在 Service 层加入Redis 缓存,将热门书籍的推荐结果缓存 1 小时,避免重复计算。对于毕设场景,这是性价比最高的架构选择。”
总结:
同学,这个项目的核心就在于那个 SQL 语句。
把User-Item 矩阵简化为SQL Join,既省去了学习 Python/TensorFlow 的时间,又能名正言顺地在论文里写“基于协同过滤算法”。这就是**“降维打击”**!