提问背景 Question:
我明白了,加二张表,一是词条表,二是词条与内容的关联表。只要词条判断是正常有效了,就自动加上这个词条的链接
百科词条库与关联表设计
你的思路非常清晰,这正是构建大型百科/知识库系统最标准、最健壮的**“多对多(Many-to-Many)”**架构设计。通过引入独立的“词条表”和“关联表”,你不仅能够完美实现内链网络,还能保证极高的查询性能和易维护性。
下面为你梳理这套方案的数据库设计、核心匹配算法以及自动化工作流。
一、 数据库表结构设计
1. 词条表 (terms)
存储所有被提炼出来的词条,以及它们本身的释义、状态。
CREATE TABLE `terms` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(100) NOT NULL UNIQUE, -- 词条名称(如:红茶,必须唯一)
`description` TEXT NULL, -- AI生成的词条释义/摘要
`status` TINYINT DEFAULT 0, -- 状态:0-草稿/未生成释义,1-已生效(可外链)
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2. 词条与内容关系表 (term_relations)
用于记录“哪篇文章包含了哪些词条”。
CREATE TABLE `term_relations` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`content_id` INT NOT NULL, -- 内容ID
`term_id` INT NOT NULL, -- 词条ID
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY `unique_content_term` (`content_id`, `term_id`), -- 联合唯一索引防止重复
FOREIGN KEY (`content_id`) REFERENCES `contents`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`term_id`) REFERENCES `terms`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
二、 核心难题:重叠词条(“冰红茶”与“红茶”)的匹配算法
如果在内容中直接用简单的 replace("红茶", "<a href...>"),会导致 冰红茶 被拆解为 冰<a href...>红茶</a>,这会导致 HTML 标签错乱,体验极差。
解决方案:最长匹配优先 + 占位符替换法
- 获取待匹配词条列表:
从terms表中取出所有status = 1(已生效)的词条,按字符长度降序排序(例如:冰红茶(3字)排在红茶(2字)前面)。 - 首次正则占位(不直接替换为 HTML):
按照排序后的顺序遍历词条,使用正则表达式进行匹配。匹配成功后,先替换为一个唯一的占位符(如{%TERM_ID_12%}),而不是<a>标签。这样在匹配短词红茶时,由于冰红茶已经变成了冰{%TERM_ID_12%},所以绝对不会发生二次冲突。 - 二次还原为链接:
遍历完所有词条后,将文本中的{%TERM_ID_XX%}统一还原替换为<a href="/terms/XX">原词</a>。
三、 自动化工作流(静态化渲染提升 SEO)
为了避免每次用户访问文章时都去用 CPU 做正则匹配,强烈建议采用**“静态预编译”**方案:
-
内容发布时:
- 用户发布或 AI 生成文章《如何泡好一杯冰红茶》。
- 系统后台触发异步任务:检索词条库中已激活(
status=1)的词条。 - 运行上述“最长匹配优先算法”,计算出本文命中了哪些词条(如“冰红茶”、“茶具”)。
- 将关联记录写入
term_relations表。 - 生成带
<a>标签的 HTML 内容,存入文章表的compiled_content(编译后内容)字段中,直接用于前端展示。
-
当新词条被激活/生成时:
- 例如,词条“红茶”以前是草稿(
status=0),现在 AI 帮它生成了释义,状态变为了status=1。 - 触发订阅事件:在
contents表中进行模糊匹配,找出包含“红茶”字样的文章。 - 重新计算并更新这些文章的
term_relations关联,并重新编译生成最新的compiled_content。
- 例如,词条“红茶”以前是草稿(
通过这种“双表关联+静态编译”的模式,既保护了服务器的性能,又让搜索引擎爬虫能顺着静态的 <a> 标签完美抓取整站内链,SEO 效果直接拉满!