likes
comments
collection
share

NestJs: 【知识库分享博客】- 数据库篇

作者站长头像
站长
· 阅读数 12

简介

之前想规划一个类似语雀的小型博客,用户分享资料、视频、文章等等,也想结合之前36镇收藏网址的设计模式。可惜后面因为某些缘故,没有继续完成这个思路的后续开发,写这篇文章主要是对一些用到的相关知识点做一下总结。

博客要素

一般一个博客都包含以下一些要素

  1. 首页:设有主题分类、热门文章、最新文章等模块,方便用户选择和浏览感兴趣的主题或文章。
  2. 文章内容:每篇文章包括标题、作者、发布时间、摘要和正文内容。通过清晰的排版和易读的文字呈现,确保读者能快速获取到想要的知识。
  3. 搜索功能:提供全文搜索功能,读者可以根据关键词搜索相关主题,让用户能快速找到感兴趣的文章。
  4. 评论和互动:为每篇文章设置评论区,读者可以对文章进行评论、提出问题或分享自己的见解。同时,可以设置点赞、分享等功能,增加读者与作者和其他读者的互动。
  5. 标签和分类:为每篇文章添加标签和分类,便于读者根据自己的兴趣和需求查找相关主题。
  6. 用户注册与登录:提供用户注册和登录功能,读者可以通过个人账户保存喜欢的文章、关注感兴趣的作者、收藏有用的资源等。
  7. 推荐和相关文章:根据读者的浏览历史和兴趣,系统可以提供相关文章推荐,使读者更容易发现和探索相关的知识。
  8. 多媒体支持:除了文字,还可以支持图片、视频等多媒体形式呈现知识内容,丰富读者的阅读体验。
  9. 管理后台:为管理员提供一个管理后台,可以管理文章的发布、编辑与删除,管理用户账户和评论,统计和分析网站流量等。
  10. 移动适应性:考虑到越来越多的用户在移动设备上访问博客,确保网站具备良好的移动适应性,可以在手机和平板上流畅阅读。

上面的要素基本是共性,展示的效果少不了UI的界面设计、互动少不了评论的元素在里面,还有就是想让更多的人访问到你的网站,除了搜索引擎SEO方面、当然还得有价值的东西的展示,就像我们买课程,也是要买对自己有价值相关的课程一样。

而我之前的设想就是将博客转换一下,如图:

NestJs: 【知识库分享博客】- 数据库篇

一个知识库,作为一个博客系统般,这样可以存储多个不同的类库话题,切换不同的体系,当然这是个比较简单的设想,可以作为练习项目的开始 下面,打算从两方面做一下总结,数据库、NestJs应用

数据库设计

知识库博客的数据库设计关系图:

                                                  +--------------+
                                                  |   用户表    |
                                                  +--------------+
                                                        |
                                                        |
                                                        |
                                                        |
                                                  +--------------+
                                                  |   知识库表    |
                          +-------------+         +--------------+
                          |   标签表    |               |
                          +-------------+         +--------------+
                                |                 |   内容表    |
                                |                 +--------------+
                                |
                                |
                          +-------------+
                          |   分类表    |
                          +-------------+
                          |             |
                          |             V
                 +-------------+  +--------------+
                 |  评论表   |     |   收藏表     |
                 +-------------+  +--------------+

在上述的关系图中,用户表存储用户的基本信息,内容表存储文章的信息,包括关联的用户、标签和分类等信息。标签表和分类表分别存储文章的标签和分类信息。评论表存储用户对文章的评论信息,收藏表存储用户收藏的文章信息。 这里主要写:

NestJs: 【知识库分享博客】- 数据库篇 这几个数据表:

知识库

CREATE TABLE `knowledge` (
  `kid` tinyint(2) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
  `cname` varchar(15) NOT NULL DEFAULT '' COMMENT '知识库名称',
  `keywords` varchar(255) DEFAULT '' COMMENT '关键词',
  `description` varchar(255) DEFAULT '' COMMENT '描述',
  `path` varchar(100) NOT NULL DEFAULT '' COMMENT '图片封面',
  `sort` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '排序',
  PRIMARY KEY (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8;

上述SQL语句创建了一个名为knowledge的表,包含以下字段:

  • kid:主键id,使用tinyint数据类型,范围是0到255,使用unsigned表示非负数。
  • cname:知识库名称,使用varchar数据类型,最大长度为15个字符,非空字段。
  • keywords:关键词,使用varchar数据类型,最大长度为255个字符,默认为空字符串。
  • description:描述,使用varchar数据类型,最大长度为255个字符,默认为空字符串。
  • path:图片封面,使用varchar数据类型,最大长度为100个字符,非空字段。
  • sort:排序,使用tinyint数据类型,范围是0到255,非空字段,默认为0。
  • PRIMARY KEY (kid)kid字段作为主键。

数据库引擎选择了InnoDB,自增起始值为29,默认字符集为utf8。

分类表

CREATE TABLE `category` (
  `cid` tinyint(2) unsigned NOT NULL AUTO_INCREMENT COMMENT '分类主键id',
  `cname` varchar(15) NOT NULL DEFAULT '' COMMENT '分类名称',
  `keywords` varchar(255) DEFAULT '' COMMENT '关键词',
  `description` varchar(255) DEFAULT '' COMMENT '描述',
  `path` varchar(100) NOT NULL DEFAULT '' COMMENT '图片封面',
  `sort` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '排序',
  `pid` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '父级栏目id',
  `kid` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '属于哪个知识库的',
  PRIMARY KEY (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8;

上述SQL语句创建了一个名为category的表,包含以下字段:

  • cid:分类主键id,使用tinyint数据类型,范围是0到255,使用unsigned表示非负数。
  • cname:分类名称,使用varchar数据类型,最大长度为15个字符,非空字段。
  • keywords:关键词,使用varchar数据类型,最大长度为255个字符,默认为空字符串。
  • description:描述,使用varchar数据类型,最大长度为255个字符,默认为空字符串。
  • path:图片封面,使用varchar数据类型,最大长度为100个字符,非空字段。
  • sort:排序,使用tinyint数据类型,范围是0到255,非空字段,默认为0。
  • pid:父级栏目id,使用tinyint数据类型,范围是0到255,非空字段,默认为0。
  • kid:属于哪个知识库的分类,使用tinyint数据类型,范围是0到255,非空字段,默认为0。
  • PRIMARY KEY (cid)cid字段作为主键。

数据库引擎选择了InnoDB,自增起始值为29,默认字符集为utf8。

内容表

CREATE TABLE `article` (
  `aid` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '文章表主键',
  `title` char(100) NOT NULL DEFAULT '' COMMENT '标题',
  `content` mediumtext NOT NULL COMMENT '文章内容',
  `url` varchar(255) NOT NULL DEFAULT '' COMMENT '链接',
  `keywords` varchar(255) NOT NULL DEFAULT '' COMMENT '关键字',
  `path` varchar(100) NOT NULL DEFAULT '' COMMENT '图片封面',
  `description` char(255) NOT NULL DEFAULT '' COMMENT '描述',
  `is_show` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '是否显示 1是 0否',
  `is_top` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '是否置顶 1是 0否'
  `click` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '点击数',
  `cid` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '分类id',
  PRIMARY KEY (`aid`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;

上述SQL语句创建了一个名为article的表,包含以下字段:

  • aid:文章表主键,使用int数据类型,长度为10,使用unsigned表示非负数。
  • title:标题,使用char数据类型,长度为100个字符,非空字段。
  • content:文章内容,使用mediumtext数据类型,非空字段。
  • url:链接,使用varchar数据类型,最大长度为255个字符,默认为空字符串。
  • keywords:关键字,使用varchar数据类型,最大长度为255个字符,默认为空字符串。
  • path:图片封面,使用varchar数据类型,最大长度为100个字符,非空字段。
  • description:描述,使用char数据类型,长度为255个字符,默认为空字符串。
  • is_show:是否显示,使用tinyint数据类型,范围是0到1,非空字段,默认为1。
  • is_top:是否置顶,使用tinyint数据类型,范围是0到1,非空字段,默认为0。
  • click:点击数,使用int数据类型,长度为10,非空字段,默认为0。
  • cid:分类id,使用tinyint数据类型,范围是0到255,非空字段,默认为0。
  • PRIMARY KEY (aid)aid字段作为主键。

数据库引擎选择了InnoDB,自增起始值为18,默认字符集为utf8。

标签表

CREATE TABLE `tag` (
  `tid` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '标签主键',
  `tname` varchar(10) NOT NULL DEFAULT '' COMMENT '标签名',
  PRIMARY KEY (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;

上述SQL语句创建了一个名为tag的表,包含以下字段:

  • tid:标签主键,使用int数据类型,长度为10,使用unsigned表示非负数。
  • tname:标签名,使用varchar数据类型,最大长度为10个字符,非空字段。

该表用于存储文章的标签信息,每个标签对应一条记录。其中,tid字段作为主键。

数据库引擎选择了InnoDB,自增起始值为21,默认字符集为utf8。

内容标签关联表

CREATE TABLE `article_tag` (
  `aid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '文章id',
  `tid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '标签id'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

上述SQL语句创建了一个名为article_tag的表,用于存储内容和标签之间的关联关系。

该表包含以下字段:

  • aid:文章id,使用int数据类型,长度为10,默认值为0,非空字段。
  • tid:标签id,使用int数据类型,长度为10,默认值为0,非空字段。

通过这个关联表,可以实现多对多关系,即一个内容可以有多个标签,一个标签可以对应多篇内容。这样的设计可以方便地查询某篇内容的全部标签,或者查询某个标签对应的所有内容。

用户表

CREATE TABLE `oauth_user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
  `uid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '关联的本站用户id',
  `type` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '类型 1:QQ  2:新浪微博 3:豆瓣 4:人人 5:开心网',
  `nickname` varchar(30) NOT NULL DEFAULT '' COMMENT '第三方昵称',
  `head_img` varchar(255) NOT NULL DEFAULT '' COMMENT '头像',
  `openid` varchar(40) NOT NULL DEFAULT '' COMMENT '第三方用户id',
  `access_token` varchar(255) NOT NULL DEFAULT '' COMMENT 'access_token token',
  `create_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '绑定时间',
  `last_login_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最后登录时间',
  `last_login_ip` varchar(16) NOT NULL DEFAULT '' COMMENT '最后登录ip',
  `login_times` int(6) unsigned NOT NULL DEFAULT '0' COMMENT '登录次数',
  `status` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '状态',
  `email` varchar(255) NOT NULL DEFAULT '' COMMENT '邮箱',
  `is_admin` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '是否是admin',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

该表包含以下字段:

  • id:主键id,使用int数据类型,长度为10,使用unsigned表示非负数。
  • uid:关联的本站用户id,使用int数据类型,长度为10,默认值为0。
  • type:类型,使用tinyint数据类型,长度为3,默认值为1。1表示QQ登录,2表示新浪微博登录,3表示豆瓣登录,4表示人人登录,5表示开心网登录。
  • nickname:第三方昵称,使用varchar数据类型,长度为30个字符,非空字段。
  • head_img:头像,使用varchar数据类型,长度为255个字符,非空字段。
  • openid:第三方用户id,使用varchar数据类型,长度为40个字符,非空字段。
  • access_token:access_token token,使用varchar数据类型,长度为255个字符,非空字段。
  • create_time:绑定时间,使用int数据类型,长度为10,默认值为0。
  • last_login_time:最后登录时间,使用int数据类型,长度为10,默认值为0。
  • last_login_ip:最后登录ip,使用varchar数据类型,长度为16个字符,非空字段。
  • login_times:登录次数,使用int数据类型,长度为6,默认值为0。
  • status:状态,使用tinyint数据类型,长度为1,默认值为1。1表示启用,0表示禁用。
  • email:邮箱,使用varchar数据类型,长度为255个字符,非空字段。
  • is_admin:是否是admin,使用tinyint数据类型,长度为1,默认值为0。1表示是管理员,0表示不是。

其中,id字段作为主键。

数据库引擎选择了InnoDB,自增起始值为2,默认字符集为utf8。

小总结:

根据创建表的SQL语句,knowledge表和category表之间存在如下关联:

  • category表的kid字段与knowledge表的kid字段相关联,用于表示一个分类属于哪一个知识库。这是一个外键关联,通过kid字段建立关联,kid字段在category表中是一个非空字段。

可以根据这个关联,通过查询category表中的kid字段,找到对应的知识库。这可以用于在知识库页面显示所属分类,或者根据知识库获取对应的分类信息。

需要注意的是,以上关联是在表结构中定义了关联字段的基础上建立的。在使用这两个表进行实际的数据库操作时,可以通过关联字段实现数据查询、插入、更新等操作。

  • tag表存储了所有的标签信息,每个标签对应一条记录。tid字段作为标签的主键,用于唯一标识一个标签。
  • article_tag表用于建立文章和标签之间的关联关系。它包含了aidtid两个字段,分别代表文章id和标签id。通过该关联表,可以实现多对多的关系,一个文章可以有多个标签,一个标签也可以对应多篇文章。
  • oauth_user表用于存储第三方登录用户的信息。该表包含了与第三方登录相关的字段,如第三方登录的类型、昵称、头像等都可以存储在该表中。还包含了用户的相关信息,如邮箱、最后登录时间等。

通过这些数据表的关联设计,我们可以进行以下操作:

  • 添加新的标签:可以向tag表中插入新的标签记录,自动生成唯一的tid作为主键。
  • 关联文章和标签:可以向article_tag表中插入新的记录,指定对应的aidtid,以建立文章和标签之间的关联关系。
  • 查询某篇文章的标签:可以通过article_tag表根据文章id(aid字段)查找对应的标签id(tid字段),然后再通过tag表查询所对应的标签信息。
  • 查询某个标签对应的所有文章:可以通过article_tag表根据标签id(tid字段)查找对应的文章id(aid字段),然后再通过文章表查询所对应的文章信息。
  • 存储第三方登录用户信息:可以将第三方登录用户的相关信息存储在oauth_user表中,并与本站的用户信息进行关联。

通过这些关联和操作,我们可以构建一个具有标签分类和第三方登录功能的知识库博客。通过标签分类,可以方便地查找和归类文章;通过第三方登录(如qq、微信),可以提供更多的登录选项和个性化的用户体验。

NestJs应用

接口设计

下面是之前设计的小部分接口,供参考:

NestJs: 【知识库分享博客】- 数据库篇

这里再说下关于一对多和多对多的知识库生成

Knowledge表:

  • 一个知识库,都有独立的一套分类 1对1
  • 一个知识库,对应多文章 1对N
  • 一个知识库,对应多标签 1对N

那么设计知识库表的时候我们可以这样映射:

NestJs: 【知识库分享博客】- 数据库篇

数据库会生成这样一个表: NestJs: 【知识库分享博客】- 数据库篇

Category表:

NestJs: 【知识库分享博客】- 数据库篇

多个分类对应一个知识库

NestJs: 【知识库分享博客】- 数据库篇

Tag表

多个标签对应一个知识库

NestJs: 【知识库分享博客】- 数据库篇

剩余的就不贴图了

当使用 TypeORM 注册数据库连接和实体后,就可以使用 NestJS 中的服务和控制器来进行数据的增删改查操作

因为边幅有限,所以登录鉴权以及控制器、业务层的实现,下一篇文章做总结。