springboot中使用mongodb完成评论功能
pom文件中引入
<!-- mongodb --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency>
yml中配置连接
data:
mongodb:
uri: mongodb://admin:123456@127.0.0.1:27017/test?authSource=admin&authMechanism=SCRAM-SHA-1
评论表字段如下(根据自己的需求设计)
public class Comment {
@Id
@ApiModelProperty(value = "评论id***********数据类型:string")
private String id;
/**
* 父级评论id
*/
@ApiModelProperty(value = "父级评论id***********数据类型:int")
private String pid;
/**
* 用户id
*/
@ApiModelProperty(value = "用户id***********数据类型:int")
private Integer customerId;
/**
* 用户姓名
*/
@ApiModelProperty(value = "用户姓名***********数据类型:string")
private String customerName;
/**
* 用户头像
*/
@ApiModelProperty(value = "用户头像***********数据类型:string")
private String customerAvatar;
/**
* 是否是会员:1:是;2:否
*/
@ApiModelProperty(value = "是否是会员:1:是;2:否***********数据类型:int")
private Integer customerIsVip;
/**
* 评论内容
*/
@ApiModelProperty(value = "评论内容***********数据类型:string")
private String content;
/**
* 评论图片
*/
@ApiModelProperty(value = "评论图片***********数据类型:string")
private String image;
/**
* 业务类型
*/
@ApiModelProperty(value = "业务类型***********数据类型:int")
private Integer busType;
/**
* 业务id
*/
@ApiModelProperty(value = "业务id***********数据类型:long")
private Long busId;
/**
* 审核状态 1:待审核;2:审核通过;3:审核失败
*/
@ApiModelProperty(value = "审核状态 1:待审核;2:审核通过;3:审核失败***********数据类型:int")
private Integer isShow;
/**
* 是否置顶 1:是;2:否
*/
@ApiModelProperty(value = "是否置顶 1:是;2:否***********数据类型:int")
private Integer isTop;
/**
* 是否是作者 1:是;2:否
*/
@ApiModelProperty(value = "是否是作者 1:是;2:否***********数据类型:int")
private Integer isAuthor;
/**
* 是否为精选评论 1:是;2:否
*/
@ApiModelProperty(value = "是否为精选评论 1:是;2:否***********数据类型:int")
private Integer isFeatured;
/**
* 是否为首评 1:是;2:否
*/
@ApiModelProperty(value = "是否为首评 1:是;2:否***********数据类型:int")
private Integer isFirst;
/**
* 被回复评论id
*/
@ApiModelProperty(value = "被回复评论id***********数据类型:int")
private String replyId;
/**
* 被回复用户id
*/
@ApiModelProperty(value = "被回复用户id***********数据类型:int")
private Integer replyCustomerId;
/**
* 是否是会员:1:是;2:否
*/
@ApiModelProperty(value = "是否是会员:1:是;2:否***********数据类型:int")
private Integer replyCustomerIsVip;
/**
* 被回复用户姓名
*/
@ApiModelProperty(value = "被回复用户姓名***********数据类型:string")
private String replyCustomerName;
/**
* 被回复用户头像
*/
@ApiModelProperty(value = "被回复用户头像***********数据类型:string")
private String replyCustomerAvatar;
/**
* 点赞数量
*/
@ApiModelProperty(value = "点赞数量***********数据类型:int")
private Integer likeCount;
/**
* 点赞状态 1:已赞;2:未赞
*/
@ApiModelProperty(value = "点赞状态 1:已赞;2:未赞***********数据类型:int")
private Integer thumbUpStatus;
/**
* 是否是朋友 0:是;1:否
*/
@ApiModelProperty(value = "点赞状态 1:已赞;2:未赞***********数据类型:int")
private Integer isFriend;
/**
* 发表时间
*/
@ApiModelProperty(value = "发表时间***********数据类型:date")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 是否是首评 1:是;2:否
*/
@ApiModelProperty(value = "是否是首评 1:是;2:否***********数据类型:int")
public Integer getIsFirst() {
return isFirst;
}
/**
* 是否是回复1级 1:是;2否
*/
@ApiModelProperty(value = "是否是回复1级 1:是;2否***********数据类型:int")
public Integer isReplyOne;
/**
* 修改时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**
* 子评论
*/
@ApiModelProperty(value = "子评论***********数据类型:obj")
private Page<AiComment> childrens;
创建CommentRespository并且继MongoRepository<Comment,String>
package com.mongo.respository;
import com.mongo.domain.Comment;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.List;
public interface CommentRespository extends MongoRepository<Comment,String> {
/**
* 通过条件查询分页
* @date 2024/10/12 18:05
* @param busType 业务类型
* @param busId 业务id
* @param isShow 是否显示
* @param pid 父id
* @param pageable 分页
* @return
*/
Page<Comment> findByBusTypeAndBusIdAndIsShowAndPid(Integer busType, Long busId, Integer isShow, String pid, Pageable pageable);
/**
* 通过评论id查询
* @date 2024/11/27 11:35
* @param id 评论id
* @param list 是否显示
* @param pageable 分页
* @return
*/
Page<Comment> findByIdAndIsShowIn(String id, List<Integer> list, Pageable pageable);
/**
* 通过业务类型和业务id查询是否存在评论
* @date 2024/11/18 10:44
* @param busType 业务类型
* @param busId 业务id
* @return
*/
List<Comment> findAiCommentByBusTypeAndAndBusId(Integer busType,Long busId);
/**
* 通过条件查询分页(如果有敏感的词自己可以查看)
* @date 2024/11/21 18:23
* @param busType 业务类型
* @param busId 业务id
* @param isShow 是否显示
* @param pid 父id
* @param busType2 业务类型
* @param busId2 业务id
* @param pid2 父id
* @param customerId 用户id
* @param list 审核状态
* @param pageable 分页
* @return
*/
Page<Comment> findByBusTypeAndBusIdAndIsShowAndPidOrBusTypeAndBusIdAndPidAndCustomerIdAndIsShowIn(Integer busType,
Long busId,
Integer isShow,
String pid,
Integer busType2,
Long busId2,
String pid2,
Integer customerId,
List<Integer> list,
Pageable pageable);
}
此MongoRepository的好处是对于一些比较简单的查询可以直接按字段组装来查询
比如findByIdAndIsShowIn 就是通过业务id和展示的状态来查询 直接见明识意
还有一种查询方式针对比较麻烦的sql语句
在respository中定义
package com.mongo.respository;
import com.mongo.domain.AiComment;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.Date;
import java.util.List;
public interface CommentRespository extends MongoRepository<Comment,String> {
/**
* 条件查询分页
* @date 2024/11/10 11:42
* @param customerId 评论人id
* @param isShow 审核状态
* @param isFeature 是否是精选
* @param startDate 开始日期
* @param endDate 结束日期
* @param pageable 分页
* @return
*/
List<Comment> findByParams(Integer customerId, Integer isShow, Integer isFeature, Date startDate, Date endDate, Pageable pageable);
/**
* 条件查询总数
* @date 2024/11/10 11:42
* @param customerId 评论人id
* @param isShow 审核状态
* @param isFeature 是否是精选
* @param startDate 开始日期
* @param endDate 结束日期
* @return java.lang.Long
*/
Long countParams(Integer customerId, Integer isShow, Integer isFeature, Date startDate, Date endDate);
}
实现类继承此类
package com.mongo.respository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import com.mongo.domain.Comment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
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.repository.query.FluentQuery;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
@Repository
public class CommentRespositoryImpl implements CommentRespository{
@Autowired
private MongoTemplate mongoTemplate;
/**
* 条件查询分页
* @date 2024/11/10 11:42
* @param customerId 评论人id
* @param isShow 审核状态
* @param isFeature 是否是精选
* @param startDate 开始日期
* @param endDate 结束日期
* @param pageable 分页
* @return
*/
@Override
public List<Comment> findByParams(Integer customerId, Integer isShow, Integer isFeature, Date startDate, Date endDate, Pageable pageable) {
Criteria criteria = new Criteria();
Query query = new Query();
if (null != customerId) {
criteria.and("customerId").is(customerId);
}
if (null != isShow) {
criteria.and("isShow").is(isShow);
}
if (null != isFeature) {
criteria.and("isFeatured").is(isFeature);
}
if (null != startDate && null != endDate) {
criteria.and("createTime").gte(startDate).lte(endDate);
} else if (startDate!= null) {
criteria.and("createTime").gte(startDate);
} else if (endDate!= null) {
criteria.and("createTime").lte(endDate);
}
query.addCriteria(criteria);
return mongoTemplate.find(query.with(pageable), Comment.class);
}
/**
* 条件查询总数
* @date 2024/11/10 11:42
* @param customerId 评论人id
* @param isShow 审核状态
* @param isFeature 是否是精选
* @param startDate 开始日期
* @param endDate 结束日期
* @return java.lang.Long
*/
@Override
public Long countParams(Integer customerId, Integer isShow, Integer isFeature, Date startDate, Date endDate) {
List<Criteria> criteriaList = new ArrayList<>();
if (null != customerId) {
criteriaList.add(Criteria.where("customerId").is(customerId));
}
if (null != isShow) {
criteriaList.add(Criteria.where("isShow").is(isShow));
}
if (null != isFeature) {
criteriaList.add(Criteria.where("isFeatured").is(isFeature));
}
if (null != startDate && null != endDate) {
criteriaList.add(Criteria.where("createTime").gte(startDate).lte(endDate));
} else if (startDate!= null) {
criteriaList.add(Criteria.where("createTime").gte(startDate));
} else if (endDate!= null) {
criteriaList.add(Criteria.where("createTime").lte(endDate));
}
if (criteriaList.isEmpty()) {
List<Comment> comments = mongoTemplate.findAll(Comment.class);
if (comments.isEmpty()) {
return 0L;
} else {
return (long) comments.size();
}
} else {
Query query = Query.query(Criteria.where("").andOperator(criteriaList.toArray(new Criteria[0])));
List<AiComment> posts = mongoTemplate.find(query, Comment.class);
if (posts.isEmpty()) {
return 0L;
} else {
return (long) posts.size();
}
}
}
}
通过Criteria和Query结合来查询
最后评论效果
评论字段说明
isReplyOne 如果是1的情况下回复一级就不显示谁回复谁
如果是一级以下的子评论isReplyOne是2就显示 张三回复李四
查询sql说明
PageRequest pageRequest = PageRequest.of(pageNum - 1, pageSize, Sort.by(Sort.Order.asc("isTop"), Sort.Order.desc("createTime"))); Page<Comment> page; if (0 == customerId) { page = aiCommentRespository.findByBusTypeAndBusIdAndIsShowAndPid(busType, busId, IsShowEnum.YES.getKey(), "0", pageRequest); } else { page = aiCommentRespository.findByBusTypeAndBusIdAndIsShowAndPidOrBusTypeAndBusIdAndPidAndCustomerIdAndIsShowIn(busType, busId, IsShowEnum.CHECK_SUCCESS.getKey(), "0", busType, busId, "0", customerId, Arrays.asList(0, 1), pageRequest); }
这里判断customerId为0是用户登陆与不登陆的情况下的操作
Arrays.asList(0, 1) 解释:因为评论可能涉及敏感信息,当用户自己评论了带有敏感的系统自动检测为敏感状态变为0(待审核状态),自己可以看到而别的用户不可以看到,所以isShow的查询条件为0,1。1为审核通过状态
findByBusTypeAndBusIdAndIsShowAndPidOrBusTypeAndBusIdAndPidAndCustomerIdAndIsShowIn
这条sql的解释:这是一条or语句
BusTypeAndBusIdAndIsShowAndPid 这是为了查询审核通过的评论
而or后面的语句是为了当本人评论了敏感的信息后可以让本人看到自己的评论而别人不可以看到
BusTypeAndBusIdAndPidAndCustomerIdAndIsShowIn
查询子评论 只需要要循环上面的评论 把pid换成主评论id即可