古诗词智能检索与推荐系统 - 项目技术阶段性总结报告
一、项目概述
1.1 项目目标
开发一个基于Spring Boot + Vue 3的古诗词智能检索与推荐系统,实现诗词数据的全文检索、个性化推荐、可视化分析和系统管理功能。
1.2 已完成工作
✅ 诗词数据采集与清洗(1000首古诗词)
✅ MySQL数据库设计与数据导入
✅ Elasticsearch索引创建与数据同步
二、详细技术实现
2.1 数据采集与预处理
数据来源:从古诗词网站爬取1000首古诗词网址(古诗词网-中国最美古诗词大全)
数据包含:标题、朝代、作者、内容、标签
数据格式:
title,dynasty,author,content,tags 八声甘州·对潇潇暮雨洒江天,宋代,柳永,"对潇潇暮雨洒江天,一番洗清秋。渐霜风凄紧,关河冷落,残照当楼。是处红衰翠减,苒苒物华休。惟有长江水,无语东流。 不忍登高临远,望故乡渺邈,归思难收。叹年来踪迹,何事苦淹留?想佳人、妆楼颙望,误几回、天际识归舟。争知我,倚阑杆处,正恁凝愁!(阑 一作:栏)",宋词三百首; 高中古诗; 写景; 抒情; 怀人; 离情; 八声甘州 寒食,唐代,韩翃,"春城无处不飞花,寒食东风御柳斜。 日暮汉宫传蜡烛,轻烟散入五侯家。",唐诗三百首; 寒食节; 典故; 讽刺; 早教; 小学生必背古诗80首 鹊桥仙·七夕,宋代,苏轼,"缑山仙子,高清云渺,不学痴牛騃女。凤箫声断月明中,举手谢时人欲去。 客槎曾犯,银河波浪,尚带天风海雨。相逢一醉是前缘,风雨散、飘然何处?",七夕节; 月夜; 送别; 豪放; 鹊桥仙 庐山谣寄卢侍御虚舟,唐代,李白,"我本楚狂人,凤歌笑孔丘。 手持绿玉杖,朝别黄鹤楼。 五岳寻仙不辞远,一生好入名山游。 庐山秀出南斗傍,屏风九叠云锦张, 影落明湖青黛光。 金阙前开二峰长,银河倒挂三石梁, 香炉瀑布遥相望,回崖沓嶂凌苍苍。 翠影红霞映朝日,鸟飞不到吴天长。 登高壮观天地间,大江茫茫去不还。 黄云万里动风色,白波九道流雪山。 好为庐山谣,兴因庐山发。 闲窥石镜清我心,谢公行处苍苔没。 早服还丹无世情,琴心三叠道初成。 遥见仙人彩云里,手把芙蓉朝玉京。 先期汗漫九垓上,愿接卢敖游太清。",唐诗三百首; 写景; 山水; 归隐; 猖狂
数据清洗:
处理中文标点符号
统一编码格式(UTF-8)
处理空值和特殊字符
标签拆分和标准化
2.2 MySQL数据库设计(8张核心表)
2.2.1 朝代表 (dynasty)
-- 1. 朝代表:存储诗词所属的历史朝代信息 CREATE TABLE `dynasty` ( `id` int PRIMARY KEY AUTO_INCREMENT, -- 朝代ID,主键,自增长 `name` varchar(20) NOT NULL UNIQUE, -- 朝代名称,唯一,非空 INDEX `idx_name` (`name`) -- 为朝代名称创建索引,加速按名称查询 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='朝代信息';
作用:存储朝代信息,规范化数据
字段说明:
id:朝代唯一标识
name:朝代名称(如"唐代"、"宋代")
数据示例:13个朝代(唐、宋、明、清等)
2.2.2 作者表 (author)
-- 2. 作者表:存储诗人信息,与朝代关联 CREATE TABLE `author` ( `id` int PRIMARY KEY AUTO_INCREMENT, -- 作者ID,主键,自增长 `name` varchar(50) NOT NULL, -- 作者姓名,非空 `dynasty_id` int, -- 所属朝代ID,外键关联朝代表 INDEX `idx_author_name` (`name`), -- 为作者姓名创建索引 CONSTRAINT `fk_author_dynasty` FOREIGN KEY (`dynasty_id`) REFERENCES `dynasty` (`id`) ON DELETE SET NULL -- 外键约束:关联朝代表,当朝代被删除时,将作者表的dynasty_id设为NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='作者信息';
作用:存储诗人信息,关联朝代
字段说明:
id:作者唯一标识
name:作者姓名
dynasty_id:所属朝代ID(外键)
数据示例:289位作者(李白、杜甫、苏轼等)
2.2.3 诗词表 (poetry) - 核心表
-- 3. 诗词表(核心表):存储诗词的详细信息 CREATE TABLE `poetry` ( `id` int PRIMARY KEY AUTO_INCREMENT, -- 诗词ID,主键,自增长 `title` varchar(200) NOT NULL, -- 诗词标题,非空 `content` text NOT NULL, -- 诗词全文,非空 `author_id` int NOT NULL, -- 作者ID,外键关联作者表 `dynasty_id` int NOT NULL, -- 朝代ID,外键关联朝代表 `tags_raw` varchar(500) DEFAULT NULL COMMENT '原始标签字符串,用于ES同步', -- 标签字符串,用于同步到Elasticsearch `content_hash` char(32) NOT NULL COMMENT 'MD5去重', -- 诗词内容的MD5哈希值,用于内容去重 `es_sync_status` tinyint DEFAULT 0 COMMENT '0-未同步,1-已同步', -- 同步到Elasticsearch的状态 `favorite_count` int DEFAULT 0 COMMENT '收藏次数', -- 被用户收藏的次数 `view_count` int DEFAULT 0 COMMENT '浏览次数', -- 被用户查看的次数 `created_at` datetime DEFAULT CURRENT_TIMESTAMP, -- 记录创建时间 `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- 记录最后更新时间 UNIQUE KEY `uk_content_hash` (`content_hash`), -- 唯一约束,确保内容不重复 INDEX `idx_title` (`title`(20)), -- 对标题前20个字符创建索引,优化标题搜索 INDEX `idx_author_id` (`author_id`), -- 作者ID索引 INDEX `idx_dynasty_id` (`dynasty_id`), -- 朝代ID索引 INDEX `idx_es_sync` (`es_sync_status`), -- 同步状态索引 CONSTRAINT `fk_poetry_author` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`) ON DELETE CASCADE, -- 外键约束:关联作者表,级联删除(作者删除时,其诗词也删除) CONSTRAINT `fk_poetry_dynasty` FOREIGN KEY (`dynasty_id`) REFERENCES `dynasty` (`id`) ON DELETE CASCADE -- 外键约束:关联朝代表,级联删除(朝代删除时,其诗词也删除) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='诗词信息';
作用:存储诗词核心信息
关键字段:
content_hash:MD5(title+author+dynasty+content),防止重复导入
es_sync_status:标记是否已同步到Elasticsearch
tags_raw:保留原始标签字符串,便于调试和ES同步
数据示例:1000首诗词
2.2.4 标签表 (tag)
-- 4. 标签表:存储诗词标签,用于分类和检索 CREATE TABLE `tag` ( `id` int PRIMARY KEY AUTO_INCREMENT, -- 标签ID,主键,自增长 `name` varchar(50) NOT NULL UNIQUE, -- 标签名称,唯一,非空 INDEX `idx_tag_name` (`name`) -- 标签名称索引 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='标签信息';
作用:存储诗词分类标签
数据示例:498个标签(思乡、山水、爱情、边塞等)
2.2.5 诗词标签关联表 (poetry_tag)
-- 5. 诗词标签关联表:多对多关系,记录诗词与标签的对应关系 CREATE TABLE `poetry_tag` ( `poetry_id` int NOT NULL, -- 诗词ID `tag_id` int NOT NULL, -- 标签ID PRIMARY KEY (`poetry_id`, `tag_id`), -- 联合主键,防止重复关联 INDEX `idx_tag_id` (`tag_id`), -- 标签ID索引,方便通过标签查找诗词 CONSTRAINT `fk_poetry_tag_poetry` FOREIGN KEY (`poetry_id`) REFERENCES `poetry` (`id`) ON DELETE CASCADE, -- 外键约束:关联诗词表,级联删除 CONSTRAINT `fk_poetry_tag_tag` FOREIGN KEY (`tag_id`) REFERENCES `tag` (`id`) ON DELETE CASCADE -- 外键约束:关联标签表,级联删除 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='诗词标签关联';
作用:实现诗词和标签的多对多关系
数据示例:4215条关联记录
2.2.6 用户表 (user)
-- 6. 用户表:存储系统用户信息 CREATE TABLE `user` ( `id` int PRIMARY KEY AUTO_INCREMENT, -- 用户ID,主键,自增长 `username` varchar(50) NOT NULL UNIQUE, -- 用户名,唯一,非空 `password` varchar(255) NOT NULL, -- 密码(加密存储) `email` varchar(100) UNIQUE, -- 邮箱,唯一 `nickname` varchar(50) DEFAULT NULL, -- 昵称 `role` varchar(20) DEFAULT 'USER' COMMENT 'ADMIN-管理员,USER-普通用户', -- 用户角色 `status` tinyint DEFAULT 1 COMMENT '0-禁用,1-正常', -- 用户状态 `created_at` datetime DEFAULT CURRENT_TIMESTAMP, -- 注册时间 `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- 最后更新时间 INDEX `idx_username` (`username`), -- 用户名索引 INDEX `idx_role` (`role`) -- 角色索引 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户信息';
作用:存储系统用户信息
角色设计:
ADMIN:管理员,可管理所有内容
USER:普通用户,可浏览、搜索、收藏
测试数据:创建了3个测试用户(admin, user1, user2)
2.2.7 用户收藏表 (user_favorite)
-- 7. 用户收藏表:记录用户收藏的诗词 CREATE TABLE `user_favorite` ( `id` int PRIMARY KEY AUTO_INCREMENT, -- 收藏记录ID,主键,自增长 `user_id` int NOT NULL, -- 用户ID `poetry_id` int NOT NULL, -- 诗词ID `created_at` datetime DEFAULT CURRENT_TIMESTAMP, -- 收藏时间 UNIQUE KEY `uk_user_poetry` (`user_id`, `poetry_id`), -- 唯一约束,防止用户重复收藏同一诗词 INDEX `idx_user_id` (`user_id`), -- 用户ID索引,方便查询用户的收藏 INDEX `idx_poetry_id` (`poetry_id`), -- 诗词ID索引,方便查询诗词的被收藏情况 CONSTRAINT `fk_user_favorite_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE, -- 外键约束:关联用户表,级联删除 CONSTRAINT `fk_user_favorite_poetry` FOREIGN KEY (`poetry_id`) REFERENCES `poetry` (`id`) ON DELETE CASCADE -- 外键约束:关联诗词表,级联删除 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户收藏记录';
作用:记录用户收藏的诗词,用于个性化推荐
数据示例:目前为空,等待用户操作
2.2.8 搜索日志表 (search_log)
-- 8. 搜索日志表:记录用户的搜索关键词,用于热门搜索分析 CREATE TABLE `search_log` ( `id` int PRIMARY KEY AUTO_INCREMENT, -- 日志ID,主键,自增长 `keyword` varchar(200) NOT NULL, -- 搜索关键词 `search_count` int DEFAULT 1, -- 搜索次数,默认1 `last_search_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- 最后搜索时间 UNIQUE KEY `uk_keyword` (`keyword`), -- 唯一约束,每个关键词只保留一条记录,通过search_count累计 INDEX `idx_search_count` (`search_count`), -- 搜索次数索引,用于排序热门关键词 INDEX `idx_last_search_time` (`last_search_time`) -- 最后搜索时间索引,用于近期热门 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='搜索日志'; show tables ;
作用:记录热门搜索词,用于搜索热词分析和可视化
数据示例:目前为空,等待用户搜索
2.3 数据库关系设计理念
规范化设计:
第一范式:每个字段都是原子性的
第二范式:消除部分依赖
第三范式:消除传递依赖
外键关系:
poetry.author_id→ author.id
poetry.dynasty_id→ dynasty.id
poetry_tag.poetry_id→ poetry.id
poetry_tag.tag_id→ tag.id
user_favorite.user_id→ user.id
user_favorite.poetry_id→ poetry.id
索引设计:
主键索引:所有表
唯一索引:用户名、邮箱、朝代名、标签名
外键索引:所有外键字段
复合索引:用户收藏表的(user_id, poetry_id)
2.4 数据导入过程
Python导入脚本关键功能:
# 1. 读取CSV文件
df = pd.read_csv('poems_with_tags.csv', encoding='utf-8', dtype=object)
# 2. 数据清洗
def clean_text(text):
# 处理空值、特殊字符、换行符
pass
# 3. 去重机制
content_hash = hashlib.md5(f"{title}|{author}|{dynasty}|{content}".encode()).hexdigest()
# 4. 分步导入
# 第一步:导入朝代
# 第二步:导入作者(关联朝代)
# 第三步:导入诗词(关联作者和朝代)
# 第四步:导入标签和关联关系
导入统计结果:
朝代:13个
作者:289位
诗词:1000首
标签:498个
诗词-标签关联:4215条
用户:3个(admin, user1, user2)
2.5 Elasticsearch索引设计与数据同步
2.5.1 Elasticsearch索引创建
索引名称:poetry_index
索引设置:
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0,
"analysis": {
"analyzer": {
"chinese_analyzer": {
"type": "custom",
"tokenizer": "ik_max_word",
"char_filter": ["html_strip"],
"filter": ["lowercase"]
},
"chinese_smart_analyzer": {
"type": "custom",
"tokenizer": "ik_smart",
"char_filter": ["html_strip"],
"filter": ["lowercase"]
}
}
}
}
}
映射设计:
{
"mappings": {
"properties": {
"id": {"type": "keyword"},
"title": {
"type": "text",
"analyzer": "chinese_analyzer",
"search_analyzer": "chinese_smart_analyzer",
"fields": {
"keyword": {"type": "keyword"}
}
},
"content": {
"type": "text",
"analyzer": "chinese_analyzer",
"search_analyzer": "chinese_smart_analyzer"
},
"authorId": {"type": "integer"},
"authorName": {
"type": "keyword",
"fields": {
"text": {"type": "text", "analyzer": "chinese_analyzer"}
}
},
"dynastyId": {"type": "integer"},
"dynastyName": {"type": "keyword"},
"tags": {
"type": "keyword",
"fields": {
"text": {"type": "text", "analyzer": "chinese_analyzer"}
}
},
"tagsRaw": {"type": "keyword"},
"favoriteCount": {"type": "integer"},
"viewCount": {"type": "integer"},
"createdAt": {"type": "date"},
"updatedAt": {"type": "date"}
}
}
}
分词器配置:
IK分词器:处理中文分词
ik_max_word:最细粒度分词(索引时使用)
ik_smart:智能分词(搜索时使用)
多字段类型:支持精确匹配和模糊搜索
停用词过滤:过滤无意义词汇
class PoetrySyncManager:
def __init__(self):
# MySQL配置
self.mysql_config = {
'host': 'localhost',
'user': 'root',
'password': '045713',
'database': 'poetry_db',
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor
}
# Elasticsearch配置
self.es_config = {
'hosts': ['http://localhost:9200'],
'timeout': 30
}
# 连接池
self.mysql_conn = None
self.es_client = None
def connect_mysql(self):
"""连接MySQL数据库"""
try:
self.mysql_conn = pymysql.connect(**self.mysql_config)
print(" MySQL连接成功")
return True
except Exception as e:
print(f" MySQL连接失败: {e}")
return False
def connect_elasticsearch(self):
"""连接Elasticsearch"""
try:
self.es_client = Elasticsearch(**self.es_config)
if self.es_client.ping():
print("Elasticsearch连接成功")
return True
else:
print("Elasticsearch连接失败")
return False
except Exception as e:
print(f" Elasticsearch连接失败: {e}")
return False
2.5.2 MySQL与Elasticsearch数据映射关系
一对一映射:
MySQL表字段 → ES文档字段 ----------------------------------------------- poetry.id → id (keyword) poetry.title → title (text) poetry.content → content (text) poetry.favorite_count → favoriteCount (integer) poetry.view_count → viewCount (integer) poetry.created_at → createdAt (date) poetry.updated_at → updatedAt (date) poetry.tags_raw → tagsRaw (keyword)
多对一映射(反规范化):
MySQL多表关联查询结果 → ES单个文档 ----------------------------------------------- author.id → authorId (integer) author.name → authorName (keyword + text) dynasty.id → dynastyId (integer) dynasty.name → dynastyName (keyword) tag.name (多行) → tags (keyword数组)
反规范化设计的好处:
查询性能:避免ES中的JOIN操作
搜索效率:一次查询返回完整信息
简化架构:降低系统复杂度
2.5.3 同步验证结果
同步统计:
总诗词数量:1000首
成功同步:1000首
同步失败:0首
ES文档总数:1000个
搜索测试结果:
搜索"明月":找到53条结果 ✓
搜索"李白":找到53条结果 ✓
2.6 技术栈配置详情
2.6.1 后端技术栈
Spring Boot 2.7.x:基础框架
Spring Data JPA:MySQL ORM
Spring Data Elasticsearch:ES客户端
Spring Security + JWT:安全认证
Spring Scheduler:定时任务
Redis:缓存(待配置)
2.6.2 前端技术栈
Vue 3.0:前端框架
Element Plus:UI组件库
Axios:HTTP客户端
Vue Router 4:路由管理
Pinia:状态管理
ECharts 5.x:数据可视化
2.6.3 数据库技术栈
MySQL 8.0:关系型数据库
Elasticsearch 8.x:搜索引擎
Redis 6.0:缓存数据库
IK Analysis:中文分词器
2.6.4 开发环境
操作系统:Windows 11
开发工具:IntelliJ IDEA , PyCharm
版本控制:Git 2.40
Java版本:JDK 8
Python版本:3.11(用于数据导入脚本)
2.7 系统架构设计
2.7.1 整体架构
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ 前端Vue 3 │ │ Spring Boot │ │ 数据库层 │ │ (用户界面) │◄──►│ (业务逻辑) │◄──►│ MySQL + ES + Redis └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ │ │ │ HTTP/JSON 服务调用/事务 数据持久化/检索
2.7.2 数据流架构
CSV数据 │ ▼ 数据清洗脚本 (Python) │ ▼ MySQL数据库 │ ├──────────────┐ ▼ ▼ 业务查询 同步脚本 │ │ ▼ ▼ 业务响应 Elasticsearch │ │ └──────┬───────┘ ▼ 前端展示
2.7.3 搜索架构
用户搜索请求 │ ▼ Spring Controller │ ▼ PoetryService │ ▼ ElasticsearchRepository │ ▼ Elasticsearch集群 │ ▼ 搜索结果处理 │ ▼ 返回JSON结果
2.8 已实现的核心功能模块
2.8.1 数据管理模块
✅ 数据采集与清洗
✅ 数据库设计与创建
✅ 数据导入与验证
✅ ES索引创建与同步
2.8.2 搜索基础模块
✅ 全文检索索引设计
✅ 中文分词器配置
✅ 基础搜索测试
2.9 项目特色与创新点
双数据库架构:MySQL负责事务和关联查询,ES负责全文检索
反规范化设计:ES中存储冗余信息,优化搜索性能
中文分词优化:IK分词器支持诗词特殊词汇
可扩展设计:模块化设计,便于功能扩展
2.10 下一步开发计划
阶段一:Spring Boot后端开发
阶段二:Vue 3前端开发
阶段三:高级功能开发(数据可视化,个性化推荐算法)
2.11 关键技术难点与解决方案
难点1:中文分词准确性
问题:古诗词有特殊词汇和句式
解决方案:使用IK分词器,配置自定义词典
难点2:搜索性能
问题:大量数据全文检索
解决方案:ES倒排索引+合理分片+缓存策略
难点4:系统安全性
问题:用户数据和系统安全
解决方案:Spring Security + JWT + 参数校验
更多推荐
所有评论(0)