网站评论功能数据库设计和开发

news/2024/5/10 8:45:49/文章来源:https://blog.csdn.net/SkipperKevin/article/details/61210306

(原文来自:http://blog.csdn.net/u010098331/article/details/51447144)

本文主要分享在设计评论模块中的一些心得,希望对读者有些许帮助。

需求分析

现阶段评论做的最好的我想应该是网易新闻(app)里面的评论模块了,其“盖楼”的方式让人印象深刻,评论已经成为该app的核心功能之一了。市面上大部分app的评论模块设计的还是相对简单的,这是可以理解的,因为评论模块不是这些app的核心功能之一。

在设计评论模块前可以和pd或者boss沟通,我们的评论功能是核心功能之一吗?实际上,90%的app采用简单的评论设计就可以了,

也就是采用一问一答,类似于如下的设计。

pic

“一问一答”这种设计十分简单、直接,也满足了用户评论、回复的基本要求,对于没有大量用户评论或者评论不是核心功能的app来说就够用了。

暂且把这种场景称之为“场景A”

如果你是新闻类或者咨询类的app,有着大量的用户评论,那么设计“盖楼”的效果还是可取的,这样能帮助用户找到该条评论或者回复的上下文情景。但是根据“盖楼”的显示效果不同,设计上也是有很大的差别的。如果是以评论为主的显示方式,类似于下面的显示方式。

pic

评论为主这里可以把评论分为“评论”和“回复”,所有的回复均挂在评论下面,类似于树状结构。把这种场景称之为“场景B”

最后就是类似于网易新闻的评论设计了,贴一张截图:

pic

同级显示这种场景下设计最为复杂,因为回复和评论是同等级的,回复还可以引用完整的回复路径,就是可以溯源到最开始的评论上。这种场景我将至称为“场景C”

MySQL数据库设计如下:

场景A

这种场景下一般评论数量较少,评论不为活跃,可以把不区分评论和回复,而统一看成评论。区别在于有的评论是直接评论主题(每个评论都挂在某个主题下,如文章、帖子等),而有些评论是@其他用户的,为了能cover这两张场景,使用一张表就可以达到效果,

评论表 如下设计:

pic

为了能复用评论模块,我们引入一个topic_type字段来区分主题的类别。

from_uid表示评论人的id,通过该id我们可以检索到评论人的相关信息。

to_uid是评论目标人的id,如果没有目标人,则该字段为空。

出于性能的考虑,往往我们会冗余评人的相关信息到评论表中,比如评论人的nick、头像等,目标用户也是如此。这样一来我们就只用查询单表就可以达到显示的效果。

有时,目标用户有多个,那么可以将to_uid字段修改为to_uids,保存时用分隔符来分割用户id,而目标用户的信息再去查询缓存或者数据库。也可以简单的将多个目标用户的信息一起存成json格式,可以应付简单的展现需求。

场景B

在以评论为主的树形显示的情况下,数据库的设计十分灵活,可以使用单表,添加一个parent_id字段来指向父评论。如果数据库本身支持嵌套查询,那么还是比较方便的,SqlServer、Oracle都支持,但是mysql不支持,那就只能通过存储过程来实现。在互联网应用中,能不使用触发器`存储过程`的话,尽量不要去使用,因为其对性能有影响。

我们还可以将评论拆分为评论表和回复表,评论挂在各种主题下面,而回复都挂在评论下面。

评论表 的设计如下:

pic

回复表 的设计如下:

pic

由于我们拆分了评论和回复,那么评论表就不再需要目标用户字段了,因为评论均是用户对主题的评论,评论表的设计更佳简洁了。

回复表我添加了一个comment_id字段来表示该回复挂在的根评论id,这样设计也是出于性能方面的考虑,我们可以直接通过评论id一次性的捞出该评论下的所有回复,然后通过程序来编排回复的显示结构。通过适当的冗余来提高性能也是常用的优化手段之一。这里给出一段我通过来评论id来查找并组织所有回复的代码:

public List<ReplyDTO> getReplyListByRid(Long rid) {
List<ReplyDO> replyDOList = replyDAO.queryReplyByCid(rid);if (replyDOList == null || replyDOList.size() == 0) {return new ArrayList<>();}List<ReplyDTO> replyDTOList = new ArrayList<>();List<ReplyDTO> parentList = new ArrayList<>();for (ReplyDO replyDO : replyDOList) {ReplyDTO replyDTO = convertReplyToDTO(replyDO);if (replyDTO.getReplyType() == ReplyType.COMMENT) {replyDTOList.add(replyDTO);parentList.add(replyDTO);} else {boolean foundParent = false;if (replyDTOList.size() > 0) {for (ReplyDTO parent : parentList) {if (parent.getId().equals(replyDTO.getReplyId())) {if (parent.getNext() == null) {parent.setNext(new ArrayList<ReplyDTO>());}parent.getNext().add(replyDTO);parentList.add(replyDTO);foundParent = true;break;}}}if (!foundParent) {throw new RuntimeException("sort reply error,should not go here.");}}}return replyDTOList;}

reply_type表示回复的类型,因为回复可以是针对评论的回复(comment),也可以是针对回复的回复(reply), 通过这个字段来区分两种情景。

reply_id表示回复目标的id,如果reply_type是comment的话,那么reply_id=commit_id,如果reply_type是reply的话,这表示这条回复的父回复。

在数据结构的设计上,我在replyDTO中设计了一个List next属性,这样在形成了一个树形的结构,类似如下树形结构:

pic

客户端可以直接根据该结构来进行树形结构的显示。

场景C

要达到网易新闻中评论的效果我还没有特别好的建议。这种场景中评论和回复是同级显示的,回复不在显示结构上不用挂在一个评论下面。双表的设计在这里就不太合适了,因为涉及到评论和回复的混排,使用双表则会导致查询的逻辑过于复杂。所以建议还是采用单表的设计,不区分评论和回复会简化应用层的逻辑。我们统一都看成评论,而有些评论是可以引用其他评论的。本人推荐采用闭包表的设计,例如:

comment表设计:

pic

parent_children表:

pic

comment表保存所有评论内容,而parent_children表则记录评论表中各个评论的父子关系。

查询时往往会按照时间排序,我们可以直接按id或者创建时间降序排列查询comment表即可。如果用户想查询一条评论的完整引用,则可以通过parent_children来找到对应的路径。向上查找到评论只需要可执行:

select parent_id from parent_children where child_id=${id} and parent_id != ${id}

向下查找所有的子孙评论可执行:

select child_id from parent_children where parent_id = ${id} and parent_id != ${id}

闭包表在查询时非常方便,但是插入的性能稍差,因为除了插入评论表以外,还需要把该条评论所有的父子关系插入到父子关系表中。插入性能会随着评论层级的加深而线性下降。

海量数据优化

如果你的系统每天都会有成千上万条评论,那么单表的设计肯定是不行,优化的方式也有很多:

分库分表。分库分表是最为常用也最有效的优化方式,建议按照主题来分库分表。这样同一个主题下面的评论就会落到同一张表里,避免了跨表查询。

适当的数据冗余。如果你需要显示评论人的相关信息,那么在插入评论时就把这些信息写入评论表中,避免多次查询。实际上,如果是纪录数据,都可以冗余对应的数据信息,因为它们的数据的实时行和一致性要求并不高,用户不会因为评论中的头像没更新而撕了你,哈哈。

附加幂等数据只允许单项操作。如果pd要求你能给评论点赞,那么你可以告诉他只能点赞,不能取消。因为从幂等性的要求来说,每个赞都是一条记录。评论的赞数如果都从点赞表中统计得出,那么性能开销会十分巨大,而且点赞如此轻量级的一个操作一定会加剧点赞表的竞争操作。所以建议直接在评论表中添加一个like_count的计数器,该字段只增不减。热门评论加缓存。类似于网易新闻的热门评论,读取频度非常高,可以专门开接口给客户端,同时该接口做缓存。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_837029.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

zblog 适合 大网站php,ZBLOG PHP网址导航主题 - 适合垂直领域轻便导航网站使用

老蒋在之前几年陆续有分享过几款基于ZBLOG PHP的导航主题模板&#xff0c;虽然并没有一直的升级更新&#xff0c;但是基本的功能还是足够用的。对于网址导航网站来说&#xff0c;最为重要的一点还是在于内容的更新&#xff0c;我们可以看到有一些个人网站导航或者行业导航&…

Python爬虫 爬取网站全部图片实战

一.获得图片地址 和 图片名称 1.进入网址之后 按F12 打开开发人员工具点击elemnts 2.点击下图的小箭头 选择主图中的任意一个图片 那我们这里点击第一个 图片 3.显示控制台 为了验证xpath是否正确 4.通过xpath获得a的href 和 title. (请放大看)我们看到 他提示的是有10个…

Python爬虫之如何抓取纯静态网站及其资源

遇到的需求 前段时间需要快速做个静态展示页面&#xff0c;要求是响应式和较美观。由于时间较短&#xff0c;自己动手写的话也有点麻烦&#xff0c;所以就打算上网找现成的。 中途找到了几个页面发现不错&#xff0c;然后就开始思考怎么把页面给下载下来。 由于之前还没有了…

用Python爬取网站的图片

爬虫这东西最早出现在我大学计算机网络的课程上面&#xff0c;我们当时的老师人很好&#xff0c;期末不笔试&#xff0c;他说这东西笔试没什么用&#xff0c;对于一个年纪比较大的老师来讲&#xff0c;能提出这种方式&#xff0c;实在难得。当时在考虑做一个与网络有关的东西好…

图片上传使用post_关于规范上传及使用网站图片的通知

由于各委员会在发布文章时没有按规定上传并使用图片&#xff0c;导致上传的图片得不到重复的利用&#xff0c;使工作效率不高&#xff0c;并浪费协会官方平台流量的问题&#xff0c;特发布本通知。请所有工作团队成员在发布新闻时按本通知要求执行。一、上传图片前要求图片在上…

html中怎么写导航栏线框,用CSS美化网站 -- 导航栏和输入框

在上一次用HTML做了一个简单的网站之后&#xff0c;小编决定用CSS来优化网站的结构并且**增添导航栏和输入框最终效果页面修改版大家可以看到在网页的左上方&#xff0c;新增加了导航栏&#xff0c;网页的左下方新增加了输入框。我们将一步一步说明这是如何实现的。导航栏CSS定…

网站云服务器清理,云服务器内存怎么清理

云服务器内存怎么清理 内容精选换一换您可以通过本节内容解决如下问题&#xff1a;用户在管理控制台执行弹性云服务器相关操作后出现异常&#xff0c;针对管理控制台提示的异常信息&#xff0c;应该如何处理&#xff1f;用户参见《弹性云服务器接口参考》调用云服务器相关的API…

网站全局变黑白灰!只需一行代码!

全国性哀悼&#xff0c;很多网站都变为灰色。 到底怎么设置的&#xff1f; 在CSS样式中添加 html {filter: grayscale(100%); } 网上很多资料都是下面这样设置的 html {filter: gray;filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale1);filter: grayscale…

VS“新建网站”与“新建Asp.Net Web 应用程序”的区别

新建网站有两种方法。 1.原来一直用的是直接新建---网站 然后添加后解决方案的项目名称是路径的名称 2.还有一种是新建--项目&#xff0c;然后选web--新建asp.net.web 项目名称是&#xff1a; 新建网站与新建Asp.Net Web 应用程序的区别&#xff1a;VS2010打sp1后&#xff0c;在…

Excel通过网站页面导入数据

选择来自XML数据导入 之后将XML文件改成所有文件就可以看到有.htm的文件&#xff0c;将htm文件打开 在一个HTML页面中选择好表格&#xff0c;之后点击确认&#xff0c;就可以将网页的表格导入Excel

搭建网站速成(1)—hello koa2

强烈安利廖雪峰老师的 koa - 廖雪峰的官方网站 (liaoxuefeng.com) 1.简单的koa2代码 -1.hello koa代码 const Koa require(koa);const app new Koa();app.use(async (ctx, next) > {await next();ctx.response.body "hello koa"; });app.listen(8000); cons…

python爬虫自学网站_Python爬虫学习——获取网页

通过GET请求获取返回的网页&#xff0c;其中加入了User-agent信息&#xff0c;不然会抛出"HTTP Error 403: Forbidden"异常&#xff0c;因为有些网站为了防止这种没有User-agent信息的访问&#xff0c;会验证请求信息中的UserAgent(它的信息包括硬件平台、系统软件、…

搜索引擎更容易识别html,什么样的网站更容易被百度搜索引擎抓取?

搜索引擎友好的网站要具备哪些条件&#xff1f;搜索引擎友好的网站要怎么做呢&#xff1f;要想做好一个让搜索引起喜欢的网站&#xff0c;小编建议你要学会换位思考&#xff0c;从搜索引擎蜘蛛的角度去思考&#xff0c;搜索引擎蜘蛛是如何看待一个网站的页面结构的&#xff1f;…

html怎么转换成app,快速把html、手机网站打包成APP的工具和步骤流程

开心app平台是我们开发的一个打包网站的工具&#xff0c;可以非常方便的把一个手机网站做成APP&#xff0c;也可以直接打包h5代码&#xff0c;免费使用&#xff01;下面介绍使用开心app平台怎么将网站快速打包成APP分七步进行1、注册开心app平台账号2、创建APP、配置基本信息3、…

php网站和asp上传方法,PHP/ASP上传漏洞探究

一、写在前面***这个上传漏洞利用的原理只是针对form格式上传的asp和php脚本***nc(netcat)用于提交数据包dos界面下运行:nc -vv www.***.com 80<1.txt-vv: 回显80: www端口1.txt: 就是你要发送的数据包(更多使用方法请查看本区的帖子)wse(wsockexpert)对本机端口的监视,抓取…

flask专题-小说网站开发一

在比较了诸多python web框架之后&#xff0c;笔者选择选择了flask框架&#xff0c;因为笔者要做推荐系统&#xff0c;收集实验数据&#xff0c;决定开发一个小型网站&#xff0c;收集信息以作后续的推荐系统&#xff0c;对于我来说flask框架完全够用。 网站网址&#xff1a;htt…

flask专题-小说网站开发二(数据准备)

在确定使用flask开发小说网站之后&#xff0c;就要准备数据了&#xff0c;数据是活的灵魂&#xff0c;没有数据就是个空架子&#xff0c;我自己不可能去写小说了&#xff0c;只能从网站采集了&#xff0c;爬虫就是利器&#xff0c;先准备一下小说数据库&#xff0c;以及整个网站…

flask专题-小说网站开发三(注册,登录)

前面几篇准备好了数据库&#xff0c;数据&#xff0c;现在开始往后开发&#xff0c;部分可能与网上他人使用方式不同&#xff0c;本人第一次做&#xff0c;功能都实现了&#xff0c;这一篇开发注册与登录&#xff0c;先贴样式 前端 登录&#xff1a; 注册&#xff1a; 前端样…

flask专题-小说网站开发四(完结)

之前断更了&#xff0c;小说网站改成基于协同过滤的图书推荐系统了&#xff0c;并已经写完&#xff0c;传到gitee了 链接 实现的功能 推荐一块使用协同过滤的思想&#xff0c;计算物品之间的相似度 web框架使用Flask&#xff0c;小说还支持在线看的 主要功能截图 用户基本模…

帝国CMS7.5开发的小说源码自适应网站源码

全网第一版帝国内核CMS7.5开发的小说源码站自适应网站源码 源码介绍 前期没有章节数据 自带采集火车头采集规则 演示地址 演示地址&#xff1a;http://www.txtzn.com