当前位置: 首页 > news >正文

获取每个评论下的回复列表[支持定位指定回复ID](基本思路+Go-Gorm实现示例)

一、表结构
CREATE TABLE `comments` (`id` int unsigned NOT NULL AUTO_INCREMENT,`publish_id` int NOT NULL COMMENT '文章/动态id',`from_uid` int NOT NULL COMMENT '评论者id',`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '内容',`ip_address` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,`ip_place` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,`deleted_at` timestamp NULL DEFAULT NULL,`created_at` timestamp NULL DEFAULT NULL,`updated_at` timestamp NULL DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='评论表';
CREATE TABLE `reply` (`id` int unsigned NOT NULL AUTO_INCREMENT,`name` varchar(255) NOT NULL DEFAULT '',`comment_id` int unsigned DEFAULT NULL,`parent_id` int unsigned DEFAULT NULL,`_lft` int DEFAULT NULL,`_rgt` int DEFAULT NULL,`created_at` datetime NOT NULL,`updated_at` datetime NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
二、回复列表嵌套节点 
  1. 新增给评论类型回复的数据(replies.reply_type="comment"):

SQL:

// 获取replies表内最大_rgt值
select COALESCE(MAX(`_rgt`), 0) from replies;// 为评论ID为1001下插入一条新的replies数据
INSERT INTO `reply` (`name`,`comment_id`,`parent_id`,`_lft`,`_rgt`,`created_at`,`updated_at`) VALUES ('节点1-1-1',1001,NULL,15,16,'2024-09-04 16:50:53.415','20209-04 16:50:53.415')

GORM:

func (tb *Reply) InsertNode() error {var maxRight int64err := db.Model(tb).Debug().Select("COALESCE(MAX(`_rgt`), 0)").Scan(&maxRight).Errorif err != nil {return err}tb.Left = maxRight + 1tb.Right = maxRight + 2tb.ParentId = nilreturn db.Debug().Create(tb).Error
}

     2. 新增给回复类型回复的数据(replies.reply_type="reply"): 

SQL:

UPDATE `reply` SET `_rgt`=_rgt + 2,`updated_at`='2024-09-04 16:58:53.728' WHERE _rgt >= 5UPDATE `reply` SET `_lft`=_lft + 2,`updated_at`='2024-09-04 16:58:53.732' WHERE _lft > 5INSERT INTO `reply` (`name`,`parent_id`,`_lft`,`_rgt`,`created_at`,`updated_at`) VALUES ('节点1-1-1',7,5,6,'2024-09-04 16:58:53.733','2024-09- 16:58:53.733')

GORM:

func (tb *Reply) AppendNode(name string) error {// 获取当前父节点的right边界值parentNodeRight := tb.Right// ps: 以下两步为了给新节点腾出空间// 更新所有右值大于或等于父节点右值的节点db.Model(&Reply{}).Debug().Where("_rgt >= ?", parentNodeRight).Update("_rgt", gorm.Expr("_rgt + 2"))// 更新左值大于父节点右值的节点db.Model(&Reply{}).Debug().Where("_lft > ?", parentNodeRight).Update("_lft", gorm.Expr("_lft + 2"))// 插入新的子节点newNode := Reply{Name:     name,ParentId: &tb.Id,Left:     parentNodeRight,Right:    parentNodeRight + 1,}return db.Debug().Create(&newNode).Error
}

     3. 获取回复嵌套列表: 

GORM:

type Reply struct {Id        int64     `json:"id"`Name      string    `json:"name"`ParentId  *int64    `json:"parent_id"`Left      int64     `json:"left" gorm:"column:_lft"`Right     int64     `json:"right" gorm:"column:_rgt"`Children  []*Reply  `json:"children" gorm:"-"`CreatedAt time.Time `json:"created_at"`UpdatedAt time.Time `json:"updated_at"`
}func GetToTree() (reply []*Reply, err error) {nodes := make([]*Reply, 0)if err = db.Order("_lft").Find(&nodes).Error; err != nil {return}nodeMap := make(map[int64]*Reply, len(nodes))reply = make([]*Reply, 0)// 构建节点映射for _, node := range nodes {nodeMap[node.Id] = node}for _, node := range nodes {if node.ParentId == nil {reply = append(reply, node)} else if parent, exists := nodeMap[*node.ParentId]; exists {parent.Children = append(parent.Children, node)}}return
}
三、展示评论列表包含回复

SQL: 


SET @row_number = 0;SET @prev_comment_id = NULL;
SELECTr.* 
FROM(SELECTreplies.*,@row_number :=IF( @prev_comment_id = replies.comment_id, @row_number + 1, 1 ) AS row_num,@prev_comment_id := replies.comment_id FROM`replies` WHEREcomment_id IN ( 32405, 32401, 32404) AND `replies`.`deleted_at` IS NULL ORDER BYreplies.comment_id DESC, FIELD(id, 30254,30256) DESC,_lft ASC ) AS r 
WHEREr.row_num <= 3;

GORM:

var repliesFieldClause stringreplies := make([]*model.Replies, 0)err = mysql.DefaultMysql.Db.Connection(func(tx *gorm.DB) (err error) {err = tx.Exec("SET @row_number = 0").Errorif err != nil {return}err = tx.Exec("SET @prev_comment_id = NULL").Errorif err != nil {return}repliesQuery := mysql.DefaultMysql.Db.Model(&model.Replies{}).Where("comment_id IN (?)", commentIDs).Select("replies.*, @row_number := IF(@prev_comment_id = replies.comment_id, @row_number + 1, 1) AS row_num, @prev_comment_id := replies.comment_id")sortReplyIDsLen := len(sortReplyIDs)if sortReplyIDsLen > 0 {sortReplyIdString := tool.IntSliceToString(sortReplyIDs)repliesFieldClause = fmt.Sprintf("replies.comment_id DESC, FIELD(id, %s) DESC, _lft ASC", sortReplyIdString)replyLimit = sortReplyIDsLen} else {repliesFieldClause = fmt.Sprintf("replies.comment_id DESC, _lft ASC")}repliesQuery.Order(repliesFieldClause)repliesSubQuery := tx.Table("(?) AS r", repliesQuery).Where("r.row_num <= ?", replyLimit).Select("r.*").Unscoped().Find(&replies)if err = repliesSubQuery.Error; err != nil {return}return})

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • EventBus-Vue事件总线解析与使用指南
  • 【Linux】使用Linux实现小程序 - 进度条
  • 计算机网络:URL构成
  • tcp 流量控制
  • Zabbix结合Grafana
  • 【进程间通信】共享内存
  • 冒泡法排序:本题要求将给定的n个整数从小到大排序后输出。输出时相邻数字中间用一个空格分开,行末不得有多余空格。
  • 【QT】学习笔记:枚举桌面窗口句柄
  • Kafka【三】Windows下安装Kafka集群
  • 使用VM创建centos7环境
  • 淘宝扭蛋机小程序开发,吸引更多的消费者
  • 海外媒体发布:12个旅游业发展媒体宣发对策,给你提升曝光量
  • 解决el-table中使用el-input无法聚焦问题
  • 加速产品研发:项目管理软件与团队的协同之道
  • easy_fastapi Python 后端开发框架
  • 11111111
  • exif信息对照
  • flutter的key在widget list的作用以及必要性
  • HTML中设置input等文本框为不可操作
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • Linux下的乱码问题
  • Swift 中的尾递归和蹦床
  • vue-loader 源码解析系列之 selector
  • 笨办法学C 练习34:动态数组
  • 测试如何在敏捷团队中工作?
  • 二维平面内的碰撞检测【一】
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 坑!为什么View.startAnimation不起作用?
  • 嵌入式文件系统
  • 一份游戏开发学习路线
  • 智能合约Solidity教程-事件和日志(一)
  • C# - 为值类型重定义相等性
  • raise 与 raise ... from 的区别
  • ​虚拟化系列介绍(十)
  • (1)无线电失控保护(二)
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (27)4.8 习题课
  • (poj1.3.2)1791(构造法模拟)
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (十八)SpringBoot之发送QQ邮件
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (转)3D模板阴影原理
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • (转)拼包函数及网络封包的异常处理(含代码)
  • **python多态
  • .chm格式文件如何阅读
  • .NET CLR Hosting 简介
  • .NET Core引入性能分析引导优化
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • /ThinkPHP/Library/Think/Storage/Driver/File.class.php  LINE: 48
  • @data注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • [ActionScript][AS3]小小笔记