@Data
@Document("db_comment")
public class DbComment {
@Id
private ObjectId id;
// 创建时间
private LocalDateTime createdAt;
// 更新时间
private LocalDateTime updatedAt;
// 删除标识
private Boolean deleted;
// 删除时间
private LocalDateTime deletedAt;
// 父评论id
private ObjectId parentId;
// 该评论的用户id
private ObjectId userId;
// 评论内容
private String content;
// 点赞的数量
private Integer likeCount;
// 回复的数量
private Integer replyCount;
// 评论类型 作品评论/文章评论
private CommentTypeEnum resourceType;
// 评论目标id 作品/文章
private ObjectId resourceId;
// 资源作者
private ObjectId resourceAuthorId;
// 是否为作者评论
private Boolean isAuthor;
// 回复用户id
private ObjectId replyToUserId;
}
这是我的评论表结构,在分页查询时,需要查询父级评论并查询文章作者的二级评论。当cid存在时,又需要将该条评论在第一页置顶,如果cid为二级评论时需要将父评论置顶,并将该评论展示出来,我可以一次将该文章下的所有评论查询出来,在代码中遍历分页,可这种操作非常占用内存效率也低。我又不希望关联查询,mongo的复杂查询很麻烦。这个cid存在时,我可以单独的对该条评论做两次查询,然后组装成commentVo 加到commentVos顶部 可这份数据又会造成多次的user信息以及是否喜欢信息的查询,还要处理Cursor以及Count结果,当c我应该怎么实现这份功能,下面的代码我并没有写当cid存在时将该条评论置顶的业务逻辑,因为很困惑!
/**
* @param commentListQuery
* @return
*/
@Override
public R<CommentResultVo> getList(CommentListQuery commentListQuery) {
ObjectId cid = commentListQuery.getCid();
ObjectId resourceId = commentListQuery.getResourceId();
Integer resourceType = commentListQuery.getResourceType();
Integer cursor = commentListQuery.getCursor();
Integer count = commentListQuery.getCount();
ObjectId userId = StpUtil.isLogin()?new ObjectId(StpUtil.getLoginIdAsString()):null;
Criteria criteria = where(DbComment.Fields.resourceId).is(resourceId).and(DbComment.Fields.resourceType).is(resourceType).and(DbComment.Fields.parentId).isNull();
long total = commentMapper.selectCount(query(criteria));
// 获取一级评论总数
Query query = query(where(DbComment.Fields.resourceId).is(resourceId).and(DbComment.Fields.resourceType).is(resourceType).and(DbComment.Fields.parentId).isNull());
query.skip(cursor);
query.limit(count);
query.with(Sort.by(Sort.Direction.DESC, BaseEntity.Fields.createdAt));
List<DbComment> dbComments = commentMapper.selectList(query);
List<ObjectId> commentIds = ConvertUtils.resultToList(dbComments, DbComment::getId);
List<ObjectId> userIds = ConvertUtils.resultToList(dbComments, DbComment::getUserId);
List<DbUser> dbUsers = userMapper.selectByIds(userIds);
Map<ObjectId, DbUser> userMap = ConvertUtils.listToMap(dbUsers, DbUser::getId);
// 点赞的评论ids
List<ObjectId> likeCommentIds = new ArrayList<>();
if (Objects.nonNull(userId)) {
List<DbLike> dbLikes = likeMapper.selectLikes(userId, commentIds, ResourceTypeEnum.COMMENT);
for (DbLike dbLike : dbLikes) {
likeCommentIds.add(dbLike.getId());
}
}
List<CommentVo> commentVos;
try(ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()){
List<CompletableFuture<CommentVo>> futures = dbComments.stream()
.map(dbComment -> CompletableFuture.supplyAsync(() -> {
CommentVo commentVo = new CommentVo();
commentVo.setId(dbComment.getId());
commentVo.setUserId(dbComment.getUserId());
if (Objects.nonNull(dbComment.getUserId())){
DbUser user = userMap.get(dbComment.getUserId());
if (Objects.nonNull(user)){
UserVo userVo = UserJson.toVo(user);
commentVo.setUser(userVo);
}
}
commentVo.setContent(dbComment.getContent());
commentVo.setReplyCount(dbComment.getReplyCount());
commentVo.setLikeCount(dbComment.getLikeCount());
commentVo.setLike(likeCommentIds.contains(dbComment.getId()));
commentVo.setAuthor(dbComment.getIsAuthor());
commentVo.setCreatedAt(dbComment.getCreatedAt());
commentVo.setUpdatedAt(dbComment.getUpdatedAt());
// 查询每个父评论的前三条子评论
Query childQuery = query(where(DbComment.Fields.parentId).is(dbComment.getId()).and(DbComment.Fields.isAuthor).is(true));
childQuery.with(Sort.by(Sort.Direction.DESC, BaseEntity.Fields.createdAt));
childQuery.limit(1);
commentVo.setSubComment(getSubComments(childQuery, userId));
return commentVo;
}, executor))
.toList();
commentVos = futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
}catch (Exception e){
commentVos= Collections.emptyList();
}
CommentResultVo pagerVo = new CommentResultVo();
pagerVo.setCursor(cursor + dbComments.size());
pagerVo.setCount(commentVos.size());
pagerVo.setTotal(total);
pagerVo.setComments(commentVos);
pagerVo.setHasMore(cursor + commentVos.size() < total);
return R.data(pagerVo);
}
要在不改变现有查询逻辑太多并且不需要进行关联查询的情况下,实现根据评论ID置顶评论的功能,你可以采取以下步骤:
cid
(如果存在)查询置顶评论(及其父评论,如果cid
是二级评论)。CommentVo
对象,并存储在一个临时列表中。以下是代码示例,展示了如何添加置顶逻辑:
// ... 其他代码 ...
// 1. 查询置顶评论
List<CommentVo> pinnedComments = new ArrayList<>();
if (Objects.nonNull(cid)) {
// 查询置顶评论,并根据需要查询其父评论
DbComment pinnedComment = commentMapper.selectById(cid); // 假设有selectById方法
if (pinnedComment != null) {
CommentVo pinnedCommentVo = convertToCommentVo(pinnedComment, userMap, likeCommentIds, userId);
pinnedComments.add(pinnedCommentVo);
// 如果cid是二级评论,查询其父评论
if (Objects.nonNull(pinnedComment.getParentId())) {
DbComment parentComment = commentMapper.selectById(pinnedComment.getParentId());
if (parentComment != null) {
CommentVo parentCommentVo = convertToCommentVo(parentComment, userMap, likeCommentIds, userId);
// 可以将父评论放在置顶列表的前面或后面,取决于你的需求
pinnedComments.add(0, parentCommentVo); // 添加到列表前面
}
}
}
}
// 2-5. 剩余逻辑...
// 在原始查询之后,合并置顶列表
List<CommentVo> finalCommentVos = new ArrayList<>(pinnedComments);
finalCommentVos.addAll(commentVos);
// 如果置顶评论数量大于分页数量,你可能需要调整分页信息
if (pinnedComments.size() > count) {
// 这里可以返回置顶评论的完整列表,或者调整cursor和total以适应设为置顶评论
// 例如,将cursor0,total设为pinnedComments.size(),并返回pinnedComments
}
// ... 其他分页逻辑和返回结果 ...
// 辅助方法,用于将DbComment转换为CommentVo
private CommentVo convertToCommentVo(DbComment dbComment, Map<ObjectId, DbUser> userMap, List<ObjectId> likeCommentIds, ObjectId userId) {
// 转换逻辑,类似于你的CompletableFuture中的代码
// ...
return commentVo;
}
注意:上述代码只是一个概念性示例,并且假设了一些方法和字段的存在。你需要根据你的实际代码库进行调整。特别是,你可能需要调整convertToCommentVo
方法以匹配你的具体需求。此外,分页逻辑(如cursor和total的调整)可能需要根据你的具体需求进行定制。
获取所有评论 GET /comments 请求查询参数: 名字 类型 描述 limit integer 可选,本次请求需要返回的数据条数。 index integer 可选,查询开始的评论位置,来源响应 id 字段。 direction string 可选,数据排序方向,以 id 进行排序,支持 asc 或 desc,默认 desc。 author integer 可选,需要筛选的评论作者,传递
评论一条资讯 获取一条资讯的评论列表 删除一条资讯评论 评论一条资讯 POST /news/{news}/comments 参数 名称 描述 body 评论内容 reply_user 被回复用户id 默认为0 Response Headers Status: 201 Created { "message": [ "操作成功" ], "comment": { "use
获取问题评论列表 获取回答评论列表 评论问题 评论答案 删除问题评论 删除回答评论 获取问题评论列表 GET /questions/:question/comments 参数 名称 类型 描述 limit Integer 默认 20 ,获取列表条数,修正值 1 - 30。 after integer 默认 0 ,筛选偏移, 上一次获取的评论列表中最后一条的id 响应 Status: 200 OK
音乐评论列表 专辑评论列表 添加音乐评论 添加专辑评论 删除音乐评论 删除专辑评论 音乐评论列表 GET /music/{music}/comments Parameters 名称 类型 描述 limit Integer 可选,默认值 15 ,获取条数 max_id Integer 可选,上次获取到数据最后一条 ID,用于获取该 ID 之后的数据。 Response Status: 200 OK
Send comment Get all comments Get a single comment Delete comment Send comment POST /feeds/:feed/comments Input Name Type Description body String Comment body. reply_user Integer Reply comment to use
一、简介 增加用户与用户,用户与管理员互动与交流。 二、功能演示 1.评论模块配置 2.评论管理 以一篇新闻的评论为例: 管理操作如下: 你可以根据自己的需要进行配置和操作。