文章目录
🙊 前言:本文章为瑞_系列专栏之《MongoDB》的案例-文章评论篇。由于博主是从B站黑马程序员的《MongoDB》学习其相关知识,所以本系列专栏主要是针对该课程进行笔记总结和拓展,文中的部分原理及图解等也是来源于黑马提供的资料,特此注明。本文仅供大家交流、学习及研究使用,禁止用于商业用途,违者必究!
5 文章评论
本文是使用 SpringDataMongoDB 简单模拟某头条的文章评论业务的实现过程
案例环境
- CentOS 7
- Java 1.8
- MongoDB Linux 4.0.10
5.1 需求分析
需要实现以下功能
1️⃣ 基本增删改查API
2️⃣ 根据文章 id 查询评论,分页效果
3️⃣ 评论点赞
5.2 表结构分析
- 数据库:
articledb
- 集合(数据表):
comment
,存放专栏文章评论
字段名称 | 字段含义 | 字段类型 | 备注 |
---|---|---|---|
_id | ID | ObjectId或String | Mongo的主键的字段 |
articleid | 文章ID | String | / |
content | 评论内容 | String | / |
userid | 评论人ID | String | / |
nickname | 评论人昵称 | String | / |
createdatetime | 评论的日期时间 | Date | / |
likenum | 点赞数 | Int32 | / |
replynum | 回复数 | Int32 | / |
state | 状态 | String | 0:不可见;1:可见; |
parentid | 上级ID | String | 如果为0表示文章的顶级评论 |
瑞:
_id
比较特殊,是 MongoDB 里面的主键,是自己生成的。其它字段都是需要演示的业务字段。
5.3 技术选型
5.3.1 mongodb-driver
mongodb-driver 是 MongoDB 官方推出的 java 连接 MongoDB 的驱动包,相当于JDBC 驱动。
官方驱动说明和下载:http://mongodb.github.io/mongo-java-driver/
官方驱动示例文档:http://mongodb.github.io/mongo-java-driver/3.8/driver/getting-started/quick-start/
5.3.2 SpringDataMongoDB
SpringData 家族成员之一,用于操作 MongoDB 的持久层框架,封装了底层的 mongodb-driver。
官网主页: https://projects.spring.io/spring-data-mongodb/
5.4 项目搭建
5.4.1 MongoDB 数据准备
MongoDB 中通过隐式创建文档的方式创建数据库articledb
和集合comment
并批量插入测试数据的命令如下⬇️
# 隐式创建数据库 articledb
use articledb
# 创建集合comment并插入数据
db.comment.insertMany([{"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date("2019-08-05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"},{"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"伊人憔悴","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"},{"_id":"3","articleid":"100001","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"杰克船长","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"},{"_id":"4","articleid":"100001","content":"专家说不能空腹吃饭,影响健康。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T08:18:35.288Z"),"likenum":NumberInt(2000),"state":"1"},{"_id":"5","articleid":"100001","content":"研究表明,刚烧开的水千万不能喝,因为烫嘴。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T11:01:02.521Z"),"likenum":NumberInt(3000),"state":"1"}]);
5.4.2 Java项目搭建
文章微服务模块搭建步骤如下
1️⃣ 使用 IDEA 创建一个 Maven 项目
2️⃣ 项目工程名称为 article
3️⃣ 在pom.xml
中引入
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 父项目引用 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.12</version>
<relativePath/>
</parent>
<groupId>com.ray.study.mongodb-study</groupId>
<artifactId>article</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
</dependencies>
</project>
4️⃣ 在resource
路径下创建application.yml
,其中地址要记得替换为你 MongoDB 服务的地址
spring:
#数据源配置
data:
mongodb:
# 主机地址
host: 192.168.133.131
# 数据库
database: articledb
# 默认端口是27017
port: 27017
# 方式二:使用uri连接
# uri: mongodb://192.168.133.131:27017/articledb
5️⃣ 创建启动类com.ray.study.mongodb.article.ArticleApplication
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 启动类
*
* @author LiaoYuXing-Ray
* @version 1.0
* @createDate 2024/5/25 13:32
**/
@SpringBootApplication
public class ArticleApplication {
public static void main(String[] args) {
SpringApplication.run(ArticleApplication.class, args);
}
}
6️⃣ 启动项目,看是否能正常启动,控制台如果没有错误则配置 MongoDB 成功
5.5 文章评论实体类的编写
1️⃣ 创建包com.ray.study.mongodb.article.po
2️⃣ 在该包下创建实体类Comment
package com.ray.study.mongodb.article.po;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 文章评论实体类
*
* <p>把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档。</p>
* <p>@Document(collection="mongodb 对应 collection 名")</p>
* <p>若未加 @Document ,该 bean save 到 mongo 的 comment collection</p>
* <p>若添加 @Document ,则 save 到 comment collection</p>
* <p></p>
*
* @author LiaoYuXing-Ray
* @version 1.0
* @createDate 2024/5/25 13:32
**/
@Document(collection="comment") // 可以省略,如果省略,则默认使用类名小写映射集合
@CompoundIndex( def = "{'userid': 1, 'nickname': -1}") // 复合索引
public class Comment implements Serializable {
// 主键标识,该属性的值会自动对应mongodb的主键字段"_id",如果该属性名就叫“id”,则该注解可以省略,否则必须写
@Id
private String id; // 主键
// 该属性对应mongodb的字段的名字,如果一致,则无需该注解
@Field("content")
private String content;// 吐槽内容
private Date publishtime;// 发布日期
// 添加了一个单字段的索引
@Indexed
private String userid; // 发布人ID
private String nickname; // 昵称
private LocalDateTime createdatetime; // 评论的日期时间
private Integer likenum; // 点赞数
private Integer replynum; // 回复数
private String state; // 状态
private String parentid; // 上级ID
private String articleid; // 文章ID
//getter and setter.....
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getPublishtime() {
return publishtime;
}
public void setPublishtime(Date publishtime) {
this.publishtime = publishtime;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public LocalDateTime getCreatedatetime() {
return createdatetime;
}
public void setCreatedatetime(LocalDateTime createdatetime) {
this.createdatetime = createdatetime;
}
public Integer getLikenum() {
return likenum;
}
public void setLikenum(Integer likenum) {
this.likenum = likenum;
}
public Integer getReplynum() {
return replynum;
}
public void setReplynum(Integer replynum) {
this.replynum = replynum;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getParentid() {
return parentid;
}
public void setParentid(String parentid) {
this.parentid = parentid;
}
public String getArticleid() {
return articleid;
}
public void setArticleid(String articleid) {
this.articleid = articleid;
}
@Override
public String toString() {
return "Comment{" +
"id='" + id + '\'' +
", content='" + content + '\'' +
", publishtime=" + publishtime +
", userid='" + userid + '\'' +
", nickname='" + nickname + '\'' +
", createdatetime=" + createdatetime +
", likenum=" + likenum +
", replynum=" + replynum +
", state='" + state + '\'' +
", parentid='" + parentid + '\'' +
", articleid='" + articleid + '\'' +
'}';
}
}
【说明】
索引可以大大提升查询效率,一般在查询字段上添加索引,索引的添加可以通过 MongoDB 的命令来添加,也可以在 Java 的实体类中通过注解添加
@Indexed注解
- 单字段索引注解@Indexed
路径:org.springframework.data.mongodb.core.index.Indexed.class
作用:声明该字段需要索引,建索引可以大大的提高查询效率
MongoDB 命令参考:db.collection_name.createIndex(keys, options)
示例
db.comment.createIndex({"userid":1})
@CompoundIndex注解
- 复合索引注解@CompoundIndex
路径:org.springframework.data.mongodb.core.index.CompoundIndex.class
作用:复合索引的声明,建复合索引可以有效地提高多字段的查询效率。
MongoDB 命令参考:db.collection_name.createIndex(keys, options)
示例
db.comment.createIndex({"userid":1,"nickname":-1})
5.6 文章评论的基本增删改查
1️⃣ 创建包com.ray.study.mongodb.article.dao
2️⃣ 创建包com.ray.study.mongodb.article.service
3️⃣ 在dao
包下创建接口CommentRepository
,要继承org.springframework.data.mongodb.repository.MongoRepository
,泛型为实体类和主键类型
import com.ray.study.mongodb.article.po.Comment;
import org.springframework.data.mongodb.repository.MongoRepository;
/**
* 评论的dao接口
*
* @author LiaoYuXing-Ray
* @version 1.0
* @createDate 2024/5/25 13:32
**/
public interface CommentRepository extends MongoRepository<Comment,String> {
}
4️⃣ 在service
包下创建CommentService
import com.ray.study.mongodb.article.dao.CommentRepository;
import com.ray.study.mongodb.article.po.Comment;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* 评论的业务层
*
* @author LiaoYuXing-Ray
* @version 1.0
* @createDate 2024/5/25 13:32
**/
@Service
public class CommentService {
// 注入dao
@Resource
private CommentRepository commentRepository;
/**
* 保存一个评论
*/
public void saveComment(Comment comment) {
// 如果需要自定义主键,可以在这里指定主键;如果不指定主键,MongoDB会自动生成主键
// 设置一些默认初始值。。。
// 调用dao
commentRepository.save(comment);
}
/**
* 更新评论
*/
public void updateComment(Comment comment) {
// 调用dao
commentRepository.save(comment);
}
/**
* 根据id删除评论
*/
public void deleteCommentById(String id) {
// 调用dao
commentRepository.deleteById(id);
}
/**
* 查询所有评论
*/
public List<Comment> findCommentList() {
// 调用dao
return commentRepository.findAll();
}
/**
* 根据id查询评论
*/
public Comment findCommentById(String id) {
// 调用dao
return commentRepository.findById(id).get();
}
}
5️⃣ 在test
包下创建com.ray.study.mongodb.article.service
包,并创建CommentServiceTest
测试类
import com.ray.study.mongodb.article.ArticleApplication;
import com.ray.study.mongodb.article.po.Comment;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
@SpringBootTest(classes = ArticleApplication.class)
public class CommentServiceTest {
// 注入Service
@Resource
private CommentService commentService;
/**
* 查询所有数据
*/
@Test
public void testFindAll(){
List<Comment> list = commentService.findCommentList();
System.out.println(list);
}
/**
* 测试根据id查询
*/
@Test
public void testFindCommentById(){
Comment comment = commentService.findCommentById("1");
System.out.println(comment);
}
/**
* 保存一个评论
*/
@Test
public void testSaveComment(){
Comment comment=new Comment();
comment.setArticleid("100000");
comment.setContent("测试添加的数据");
comment.setCreatedatetime(LocalDateTime.now());
comment.setUserid("1003");
comment.setNickname("凯撒大帝");
comment.setState("1");
comment.setLikenum(0);
comment.setReplynum(0);
commentService.saveComment(comment);
System.out.println("写入数据成功");
}
}
6️⃣ 可以执行测试查询、新增方法,查看是否成功
5.7 根据上级ID查询文章评论的分页列表
1️⃣ CommentRepository
新增方法findByParentid
瑞:注意语法格式,findBy是固定写法,ParentId 对应字段名
import com.ray.study.mongodb.article.po.Comment;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;
/**
* 评论的dao接口
*
* @author LiaoYuXing-Ray
* @version 1.0
* @createDate 2024/5/25 13:32
**/
public interface CommentRepository extends MongoRepository<Comment,String> {
// 根据父id,查询子评论的分页列表
Page<Comment> findByParentid(String parentid, Pageable pageable);
}
2️⃣ CommentService
新增方法findCommentListPageByParentid
/**
* 根据父id查询分页列表
*
* @param parentId 父ID
* @param page 页码
* @param size 每页显示的数据量
*/
public Page<Comment> findCommentListPageByParentid(String parentId, int page, int size) {
// 为什么要page-1?因为参数穿进去的是zero-based page index. 是基于0开始的索引的页码
return commentRepository.findByParentid(parentId, PageRequest.of(page - 1, size));
}
3️⃣ CommentServiceTest
中新增测试方法testFindCommentListPageByParentid
/**
* 测试根据父id查询子评论的分页列表
*/
@Test
public void testFindCommentListPageByParentid(){
Page<Comment> pageResponse = commentService.findCommentListPageByParentid("3", 1, 2);
System.out.println("----总记录数:"+pageResponse.getTotalElements());
System.out.println("----当前页数据:"+pageResponse.getContent());
}
4️⃣ 在MongoDB 的articledb
数据库下的comment
中添加一条parentid
为 3 的数据
db.getCollection("comment").insert( {
_id: "6",
parentid: "3",
articleid: "100001",
content: "研究表明,刚烧开的水千万不能喝,因为很烫。",
userid: "1003",
nickname: "瑞神",
createdatetime: ISODate("2024-05-25T15:21:12.521Z"),
likenum: NumberInt("486"),
state: "1"
} );
5️⃣ 运行测试方法testFindCommentListPageByParentid
,结果如下,能查到一条数据
----总记录数:1
----当前页数据:[Comment{id='6', content='研究表明,刚烧开的水千万不能喝,因为很烫。', publishtime=null, userid='1003', nickname='瑞神', createdatetime=2024-05-25T23:21:12.521, likenum=486, replynum=null, state='1', parentid='3', articleid='100001'}]
5.8 MongoTemplate实现评论点赞(修改操作)
推荐使用
MongoTemplate
类来实现对某列的操作
引入:以下为效率低的实现示例,CommentService
新增updateThumbup
方法
/**
* 点赞-效率低
*/
public void updateCommentThumbupToIncrementingOld(String id) {
Comment comment = CommentRepository.findById(id).get();
comment.setLikenum(comment.getLikenum() + 1);
CommentRepository.save(comment);
}
以上方法虽然实现起来比较简单,但是执行效率并不高,因为我只需要将点赞数加 1 就可以了,没必要查询出所有字段修改后再更新所有字段。(蝴蝶效应)
所以我们可以使用MongoTemplate
类来实现对某列的操作,如下
1️⃣ CommentService
中注入MongoTemplate
// 注入MongoTemplate
@Resource
private MongoTemplate mongoTemplate;
2️⃣ CommentService
中添加方法updateCommentLikenum
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
/**
* 点赞数+1
*/
public void updateCommentLikenumThumbup(String id) {
// 查询对象
Query query = Query.query(Criteria.where("_id").is(id));
// 更新对象
// Update update = Update.update(key, value)
Update update = new Update();
// 局部修改,相当于$set
// update.set(key, value)
// 对赞数列递增1
// update.inc("likenum", 1);
update.inc("likenum");
// 更新点赞数
// 参数1:查询对象
// 参数2:更新对象
// 参数3:集合的名字或实体类的类型Comment.class
mongoTemplate.updateFirst(query, update, "comment");
}
3️⃣ CommentServiceTest
中添加测试方法testUpdateCommentLikenumThumbup
/**
* 点赞数+1
*/
@Test
public void testUpdateCommentLikenumThumbup() {
System.out.println("点赞前:" + commentService.findCommentById("3"));
// 对3号文档的点赞数+1
commentService.updateCommentLikenumThumbup("3");
System.out.println("点赞后:" + commentService.findCommentById("3"));
}
4️⃣ 运行测试方法testUpdateCommentLikenumThumbup
,结果如下,likenum 从 666 增长为 667
点赞前:Comment{id='3', content='我一直喝凉开水,冬天夏天都喝。', publishtime=null, userid='1004', nickname='杰克船长', createdatetime=2019-08-06T09:05:06.321, likenum=666, replynum=null, state='1', parentid='null', articleid='100001'}
点赞后:Comment{id='3', content='我一直喝凉开水,冬天夏天都喝。', publishtime=null, userid='1004', nickname='杰克船长', createdatetime=2019-08-06T09:05:06.321, likenum=667, replynum=null, state='1', parentid='null', articleid='100001'}
附:完整的代码
article【瑞_MongoDB_案例-文章评论】
的完整源码的某度网盘链接如下,需要自取
链接:https://pan.baidu.com/s/1FMNAZNkXYm8kSbv18A6RDw?pwd=a7r4
提取码:a7r4
项目架构图
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 父项目引用 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.12</version>
<relativePath/>
</parent>
<groupId>com.ray.study.mongodb-study</groupId>
<artifactId>article</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
</dependencies>
</project>
application.yml
spring:
#数据源配置
data:
mongodb:
# 主机地址
host: 192.168.133.131
# 数据库
database: articledb
# 默认端口是27017
port: 27017
# 方式二:使用uri连接
# uri: mongodb://192.168.133.131:27017/articledb
ArticleApplication
package com.ray.study.mongodb.article;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 启动类
*
* @author LiaoYuXing-Ray
* @version 1.0
* @createDate 2024/5/25 13:32
**/
@SpringBootApplication
public class ArticleApplication {
public static void main(String[] args) {
SpringApplication.run(ArticleApplication.class, args);
}
}
Comment
package com.ray.study.mongodb.article.po;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 文章评论实体类
*
* <p>把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档。</p>
* <p>@Document(collection="mongodb 对应 collection 名")</p>
* <p>若未加 @Document ,该 bean save 到 mongo 的 comment collection</p>
* <p>若添加 @Document ,则 save 到 comment collection</p>
* <p></p>
*
* @author LiaoYuXing-Ray
* @version 1.0
* @createDate 2024/5/25 13:32
**/
@Document(collection="comment") // 可以省略,如果省略,则默认使用类名小写映射集合
@CompoundIndex( def = "{'userid': 1, 'nickname': -1}") // 复合索引
public class Comment implements Serializable {
// 主键标识,该属性的值会自动对应mongodb的主键字段"_id",如果该属性名就叫“id”,则该注解可以省略,否则必须写
@Id
private String id; // 主键
// 该属性对应mongodb的字段的名字,如果一致,则无需该注解
@Field("content")
private String content;// 吐槽内容
private Date publishtime;// 发布日期
// 添加了一个单字段的索引
@Indexed
private String userid; // 发布人ID
private String nickname; // 昵称
private LocalDateTime createdatetime; // 评论的日期时间
private Integer likenum; // 点赞数
private Integer replynum; // 回复数
private String state; // 状态
private String parentid; // 上级ID
private String articleid; // 文章ID
//getter and setter.....
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getPublishtime() {
return publishtime;
}
public void setPublishtime(Date publishtime) {
this.publishtime = publishtime;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public LocalDateTime getCreatedatetime() {
return createdatetime;
}
public void setCreatedatetime(LocalDateTime createdatetime) {
this.createdatetime = createdatetime;
}
public Integer getLikenum() {
return likenum;
}
public void setLikenum(Integer likenum) {
this.likenum = likenum;
}
public Integer getReplynum() {
return replynum;
}
public void setReplynum(Integer replynum) {
this.replynum = replynum;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getParentid() {
return parentid;
}
public void setParentid(String parentid) {
this.parentid = parentid;
}
public String getArticleid() {
return articleid;
}
public void setArticleid(String articleid) {
this.articleid = articleid;
}
@Override
public String toString() {
return "Comment{" +
"id='" + id + '\'' +
", content='" + content + '\'' +
", publishtime=" + publishtime +
", userid='" + userid + '\'' +
", nickname='" + nickname + '\'' +
", createdatetime=" + createdatetime +
", likenum=" + likenum +
", replynum=" + replynum +
", state='" + state + '\'' +
", parentid='" + parentid + '\'' +
", articleid='" + articleid + '\'' +
'}';
}
}
CommentRepository
package com.ray.study.mongodb.article.dao;
import com.ray.study.mongodb.article.po.Comment;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;
/**
* 评论的dao接口
*
* @author LiaoYuXing-Ray
* @version 1.0
* @createDate 2024/5/25 13:32
**/
public interface CommentRepository extends MongoRepository<Comment,String> {
// 根据父id,查询子评论的分页列表
Page<Comment> findByParentid(String parentid, Pageable pageable);
}
CommentService
package com.ray.study.mongodb.article.service;
import com.ray.study.mongodb.article.dao.CommentRepository;
import com.ray.study.mongodb.article.po.Comment;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* 评论的业务层
*
* @author LiaoYuXing-Ray
* @version 1.0
* @createDate 2024/5/25 13:32
**/
@Service
public class CommentService {
// 注入dao
@Resource
private CommentRepository commentRepository;
/**
* 保存一个评论
*/
public void saveComment(Comment comment) {
// 如果需要自定义主键,可以在这里指定主键;如果不指定主键,MongoDB会自动生成主键
// 设置一些默认初始值。。。
// 调用dao
commentRepository.save(comment);
}
/**
* 更新评论
*/
public void updateComment(Comment comment) {
// 调用dao
commentRepository.save(comment);
}
/**
* 根据id删除评论
*/
public void deleteCommentById(String id) {
// 调用dao
commentRepository.deleteById(id);
}
/**
* 查询所有评论
*/
public List<Comment> findCommentList() {
// 调用dao
return commentRepository.findAll();
}
/**
* 根据id查询评论
*/
public Comment findCommentById(String id) {
// 调用dao
return commentRepository.findById(id).get();
}
/**
* 根据父id查询分页列表
*
* @param parentId 父ID
* @param page 页码
* @param size 每页显示的数据量
*/
public Page<Comment> findCommentListPageByParentid(String parentId, int page, int size) {
// 为什么要page-1?因为参数穿进去的是zero-based page index. 是基于0开始的索引的页码
return commentRepository.findByParentid(parentId, PageRequest.of(page - 1, size));
}
// 注入MongoTemplate
@Resource
private MongoTemplate mongoTemplate;
/**
* 点赞数+1
*/
public void updateCommentLikenumThumbup(String id) {
// 查询对象
Query query = Query.query(Criteria.where("_id").is(id));
// 更新对象
// Update update = Update.update(key, value)
Update update = new Update();
// 局部修改,相当于$set
// update.set(key, value)
// 对赞数列递增1
// update.inc("likenum", 1);
update.inc("likenum");
// 更新点赞数
// 参数1:查询对象
// 参数2:更新对象
// 参数3:集合的名字或实体类的类型Comment.class
mongoTemplate.updateFirst(query, update, "comment");
}
}
CommentServiceTest
package com.ray.study.mongodb.article.service;
import com.ray.study.mongodb.article.ArticleApplication;
import com.ray.study.mongodb.article.po.Comment;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
@SpringBootTest(classes = ArticleApplication.class)
public class CommentServiceTest {
// 注入Service
@Resource
private CommentService commentService;
/**
* 查询所有数据
*/
@Test
public void testFindAll() {
List<Comment> list = commentService.findCommentList();
System.out.println(list);
}
/**
* 测试根据id查询
*/
@Test
public void testFindCommentById() {
Comment comment = commentService.findCommentById("1");
System.out.println(comment);
}
/**
* 保存一个评论
*/
@Test
public void testSaveComment() {
Comment comment = new Comment();
comment.setArticleid("100000");
comment.setContent("测试添加的数据");
comment.setCreatedatetime(LocalDateTime.now());
comment.setUserid("1003");
comment.setNickname("凯撒大帝");
comment.setState("1");
comment.setLikenum(0);
comment.setReplynum(0);
commentService.saveComment(comment);
System.out.println("写入数据成功");
}
/**
* 测试根据父id查询子评论的分页列表
*/
@Test
public void testFindCommentListPageByParentid() {
Page<Comment> pageResponse = commentService.findCommentListPageByParentid("3", 1, 2);
System.out.println("----总记录数:" + pageResponse.getTotalElements());
System.out.println("----当前页数据:" + pageResponse.getContent());
}
/**
* 点赞数+1
*/
@Test
public void testUpdateCommentLikenumThumbup() {
System.out.println("点赞前:" + commentService.findCommentById("3"));
// 对3号文档的点赞数+1
commentService.updateCommentLikenumThumbup("3");
System.out.println("点赞后:" + commentService.findCommentById("3"));
}
}
如果觉得这篇文章对您有所帮助的话,请动动小手点波关注💗,你的点赞👍收藏⭐️转发🔗评论📝都是对博主最好的支持~