圈子互动
点赞、喜欢、评论等均可理解为用户对动态的互动。
mongodb中的数据
- 在动态详情Movement表中,加入喜欢,点赞,评论数量:减少数据库访问压力
- 圈子互动的表 comment
- 互动完成(点赞,喜欢):不仅要将数据保存到mongo中,需要记录到redis中
- 页面查询圈子列表时,可以从redis中判断是否有点赞,和喜欢历史
二、环境搭建
在动态详情表中补充字段
| @Data |
| @NoArgsConstructor |
| @AllArgsConstructor |
| @Document(collection = "movement") |
| public class Movement implements java.io.Serializable { |
| |
| private ObjectId id; |
| |
| private Long pid; |
| private Long created; |
| private Long userId; |
| private String textContent; |
| private List<String> medias; |
| private String longitude; |
| private String latitude; |
| private String locationName; |
| private Integer state = 0; |
| |
| |
| private Integer likeCount = 0; |
| private Integer commentCount = 0; |
| private Integer loveCount = 0; |
| |
| |
| public Integer statisCount(Integer commentType) { |
| if (commentType == CommentType.LIKE.getType()) { |
| return this.likeCount; |
| } else if (commentType == CommentType.COMMENT.getType()) { |
| return this.commentCount; |
| } else { |
| return loveCount; |
| } |
| } |
| } |
实体类
Comment
| package com.tanhua.domain.mongo; |
| |
| import lombok.AllArgsConstructor; |
| import lombok.Data; |
| import lombok.NoArgsConstructor; |
| import org.bson.types.ObjectId; |
| import org.springframework.data.mongodb.core.mapping.Document; |
| |
| |
| |
| |
| @Data |
| @NoArgsConstructor |
| @AllArgsConstructor |
| @Document(collection = "comment") |
| public class Comment implements java.io.Serializable{ |
| |
| private ObjectId id; |
| private ObjectId publishId; |
| private Integer commentType; |
| private String content; |
| private Long userId; |
| private Long publishUserId; |
| private Long created; |
| private Integer likeCount = 0; |
| |
| } |
vo
| @Data |
| @NoArgsConstructor |
| @AllArgsConstructor |
| public class CommentVo implements Serializable { |
| |
| private String id; |
| private String avatar; |
| private String nickname; |
| |
| |
| private String content; |
| private String createDate; |
| private Integer likeCount; |
| private Integer hasLiked; |
| |
| public static CommentVo init(UserInfo userInfo, Comment item) { |
| CommentVo vo = new CommentVo(); |
| BeanUtils.copyProperties(userInfo, vo); |
| BeanUtils.copyProperties(item, vo); |
| vo.setHasLiked(0); |
| Date date = new Date(item.getCreated()); |
| vo.setCreateDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date)); |
| vo.setId(item.getId().toHexString()); |
| return vo; |
| } |
| } |
CommentType枚举
| |
| |
| |
| public enum CommentType { |
| |
| LIKE(1), COMMENT(2), LOVE(3); |
| |
| int type; |
| |
| CommentType(int type) { |
| this.type = type; |
| } |
| |
| public int getType() { |
| return type; |
| } |
| } |
api接口
| public interface CommentApi { |
| |
| } |
api实现类
| @DubboService |
| public class CommentApiImpl implements CommentApi { |
| |
| @Autowired |
| private MongoTemplate mongoTemplate; |
| } |
三、动态评论
功能包括:查询评论列表,发布评论,对评论点赞和取消点赞。
1. 发布评论
Controller
| |
| |
| |
| |
| |
| |
| |
| @PostMapping |
| public ResponseEntity postCommen(@RequestBody Map map){ |
| |
| String movementId = (String) map.get("movementId"); |
| String comment = (String) map.get("comment"); |
| |
| commentService.postCommon(movementId,comment); |
| return ResponseEntity.ok(null); |
| } |
Service
| |
| |
| |
| |
| |
| |
| public void postCommon(String movementId, String text) { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| Comment comment = new Comment(); |
| comment.setPublishId(new ObjectId(movementId)); |
| comment.setCommentType(CommentType.COMMENT.getType()); |
| comment.setContent(text); |
| comment.setUserId(ThreadLocalUtils.getUserId()); |
| comment.setCreated(System.currentTimeMillis()); |
| |
| |
| Integer integer = commentApi.postCommen(comment); |
| |
| |
| } |
| |
api层
| |
| |
| |
| |
| public Integer postCommen(Comment comment) { |
| |
| |
| |
| |
| ObjectId publishId = comment.getPublishId(); |
| Movement movement = mongoTemplate.findById(publishId, Movement.class); |
| comment.setPublishUserId(movement.getUserId()); |
| |
| |
| mongoTemplate.save(comment); |
| |
| |
| |
| |
| Criteria criteria = Criteria.where("id").is(comment.getPublishId()); |
| Query query = Query.query(criteria); |
| |
| |
| Update update = new Update(); |
| |
| if(comment.getCommentType() == CommentType.LIKE.getType()){ |
| update.inc("likeCount",1); |
| }else if(comment.getCommentType() == CommentType.COMMENT.getType()){ |
| update.inc("commentCount",1); |
| }else{ |
| update.inc("loveCount", 1); |
| } |
| |
| FindAndModifyOptions options = new FindAndModifyOptions(); |
| options.returnNew(true); |
| |
| |
| Movement modify = mongoTemplate.findAndModify(query, update, options, Movement.class); |
| |
| Integer count = modify.statisCount(comment.getCommentType()); |
| return count; |
| } |
| |
2.分页列表查询评论
controller
| |
| |
| |
| |
| |
| |
| |
| |
| |
| @GetMapping |
| public ResponseEntity lookComments(String movementId, |
| @RequestParam(defaultValue = "1") Integer page, |
| @RequestParam(defaultValue = "10") Integer pageSize){ |
| PageResult pageResult = commentService.lookComments(movementId,page,pageSize); |
| return ResponseEntity.ok(pageResult); |
| } |
Service
| |
| |
| |
| |
| |
| public PageResult lookComments(String movementId, Integer page, Integer pageSize) { |
| |
| |
| List<Comment> comments = commentApi.lookComments(movementId, page, pageSize, CommentType.COMMENT.getType()); |
| |
| if(CollUtil.isEmpty(comments)){ |
| return new PageResult(); |
| } |
| |
| List<Long> userIds = CollUtil.getFieldValues(comments, "userId", Long.class); |
| Map<Long, UserInfo> userInfoMap = userInfoApi.batchQueryUserInfo(userIds, null); |
| |
| List<CommentVo> commentVos = new ArrayList<>(); |
| |
| for (Comment comment : comments) { |
| Long id = comment.getUserId(); |
| UserInfo userInfo = userInfoMap.get(id); |
| if(userInfo != null){ |
| CommentVo commentVo = CommentVo.init(userInfo, comment); |
| commentVos.add(commentVo); |
| } |
| } |
| |
| PageResult pageResult = new PageResult(page,pageSize,0,commentVos); |
| return pageResult; |
| |
| } |
| |
| |
api
| |
| |
| |
| |
| |
| |
| public List<Comment> lookComments(String movementId, Integer page, Integer pageSize, int type) { |
| |
| |
| Criteria criteria = Criteria.where("publishId").is(new ObjectId(movementId)).and("commentType").is(type); |
| |
| |
| Query query = Query.query(criteria); |
| query.skip(( page - 1) * pageSize ).limit(pageSize).with(Sort.by(Sort.Order.desc("created"))); |
| |
| List<Comment> comments = mongoTemplate.find(query, Comment.class); |
| |
| return comments; |
| } |
3.动态点赞
MovementController
| |
| |
| |
| |
| |
| |
| |
| @GetMapping({"/{id}/like"}) |
| public ResponseEntity like(@PathVariable("id") String id){ |
| Integer integer = commentService.like(id); |
| return ResponseEntity.ok(integer); |
| } |
| |
| |
| |
| |
| public Integer like(String movementId) { |
| |
| |
| Boolean result = commentApi.isLike(ThreadLocalUtils.getUserId(), movementId,CommentType.LIKE); |
| |
| if(result){ |
| throw new BusinessException(ErrorResult.likeError()); |
| } |
| |
| |
| Comment comment = new Comment(); |
| comment.setPublishId(new ObjectId(movementId)); |
| comment.setCommentType(CommentType.LIKE.getType()); |
| comment.setUserId(ThreadLocalUtils.getUserId()); |
| comment.setCreated(System.currentTimeMillis()); |
| |
| Integer count = commentApi.postCommen(comment); |
| |
| |
| |
| String key = Constants.MOVEMENTS_INTERACT_KEY +movementId; |
| String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + ThreadLocalUtils.getUserId(); |
| redisTemplate.opsForHash().put(key, hashKey, "1"); |
| |
| return count; |
| } |
| |
api
| |
| |
| |
| public Boolean isLike(Long userId, String movementId, CommentType commentType) { |
| Criteria criteria = Criteria.where("userId").is(userId) |
| .and("publishId").is(new ObjectId(movementId)) |
| .and("commentType").is(commentType.getType()); |
| Query query = Query.query(criteria); |
| boolean result = mongoTemplate.exists(query, Comment.class); |
| |
| return result; |
| } |
| |
| |
| |
| |
4.取消点赞
MovementController
| |
| |
| |
| |
| |
| |
| @GetMapping("/{id}/dislike") |
| public ResponseEntity disLike(@PathVariable("id") String id){ |
| Integer count = commentService.disLikeComment(id); |
| return ResponseEntity.ok(count); |
| } |
| |
| |
| |
| |
| |
| public Integer disLikeComment(String movementId) { |
| |
| |
| Boolean result = commentApi.isLike(ThreadLocalUtils.getUserId(),movementId,CommentType.LIKE); |
| |
| if(!result){ |
| |
| throw new BusinessException(ErrorResult.disLikeError()); |
| } |
| |
| Comment comment = new Comment(); |
| comment.setPublishId(new ObjectId(movementId)); |
| comment.setUserId(ThreadLocalUtils.getUserId()); |
| comment.setCommentType(CommentType.LIKE.getType()); |
| comment.setCreated(System.currentTimeMillis()); |
| |
| Integer count = commentApi.delete(comment); |
| |
| |
| |
| String key = Constants.MOVEMENTS_INTERACT_KEY + movementId; |
| String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + ThreadLocalUtils.getUserId(); |
| |
| redisTemplate.opsForHash().delete(key, hashKey); |
| |
| return count; |
| } |
5.动态喜欢
Controller
| |
| |
| |
| |
| |
| |
| |
| |
| |
| @GetMapping("/{id}/love") |
| public ResponseEntity loveMovement(@PathVariable("id") String movementId){ |
| Integer count = commentService.saveLoveMovement(movementId); |
| return ResponseEntity.ok(count); |
| } |
Service
| |
| |
| |
| |
| public Integer saveLoveMovement(String movementId) { |
| |
| Boolean result = commentApi.isLike(ThreadLocalUtils.getUserId(),movementId,CommentType.LOVE); |
| |
| |
| |
| if(result){ |
| |
| throw new BusinessException(ErrorResult.loveError()); |
| } |
| |
| |
| Comment comment = new Comment(); |
| comment.setPublishId(new ObjectId(movementId)); |
| comment.setCommentType(CommentType.LOVE.getType()); |
| comment.setUserId(ThreadLocalUtils.getUserId()); |
| comment.setCreated(System.currentTimeMillis()); |
| |
| Integer count = commentApi.postCommen(comment); |
| |
| String key = Constants.MOVEMENTS_INTERACT_KEY + comment.getPublishId(); |
| String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + ThreadLocalUtils.getUserId(); |
| redisTemplate.opsForHash().hasKey(key, hashKey); |
| |
| |
| return count; |
| } |
| |
| |
6.取消喜欢动态
Controller
| |
| |
| |
| |
| |
| |
| |
| |
| @GetMapping("/{id}/unlove") |
| public ResponseEntity unLove(@PathVariable("id") String movementId){ |
| Integer count = commentService.unLOve(movementId); |
| |
| return ResponseEntity.ok(count); |
| } |
Service
| |
| |
| |
| |
| public Integer unLOve(String movementId) { |
| |
| Boolean result = commentApi.isLike(ThreadLocalUtils.getUserId(), movementId, CommentType.LOVE); |
| |
| if(!result){ |
| throw new BusinessException(ErrorResult.disloveError()); |
| } |
| |
| |
| Comment comment = new Comment(); |
| comment.setPublishId(new ObjectId(movementId)); |
| comment.setCommentType(CommentType.LOVE.getType()); |
| comment.setUserId(ThreadLocalUtils.getUserId()); |
| comment.setCreated(System.currentTimeMillis()); |
| Integer count = commentApi.delete(comment); |
| |
| String key = Constants.MOVEMENTS_INTERACT_KEY + comment.getPublishId(); |
| String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + ThreadLocalUtils.getUserId(); |
| |
| redisTemplate.opsForHash().delete(key, hashKey); |
| |
| return count; |
| } |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端