day09-MongoDB


day09-MongoDB

一、回顾

1.1. 行为实战核心要点说明

  • 技术方案
    Redis+MySQL
    Redis:负责对外提供读与写,因为行为对读写的性能很高,不能直接去操作MySQL
    MySQL:基于MQ实现异步数据同步,(不使用线程池的原因是因为Threadpool是基于本地内存的,不能把大量的数据放在线程池里,数据量过多),Redis操作完数据,把更改的数据同步到MySQL的行为表中
  • 各行为接口
    • user服务
      • 关注与取消关注接口
      • Redis设计:
        • ZSET——关注列表
          • key:behavior:follow:list:当前用户ID
          • score:关注的时间
          • value:作者的用户ID
        • ZSET——粉丝列表
          • key:behavior:follow:list:当前用户ID
          • score:被关注的时间
          • value:粉丝的用户ID
    • article服务
      • 收藏与取消收藏接口
      • Redis设计-HASH类型
        • key:behavior:coll:当前用户ID
        • value:
          • key:文章ID
          • value:文章详情
      • 文章行为关系数据查询接口
    • behavior服务
      • 点赞与取消点赞接口
      • Redis设计-HASH类型
        • key:behavior:likes:文章ID
        • value:
          • key:用户ID
          • value:操作的详情
      • 阅读接口
      • 不喜欢与取消不喜欢接口

二、评论系统

2.1 MongoDB

2.1.1 MongoDB简介

①简介

端口号:27017
默认不支持事务
MongoDB是一个开源、高性能、无模式的文档型数据库
是NoSQL数据库产品中的一种,是最像关系型数据库(MySQL)的非关系性数据库

  • 数据存储量较大,甚至巨大
  • 对数据读写的响应速度要求非常高
  • 某些数据安全性要求不高,可以接收一定范围内的误差
  • 数据具有结构型(BSON)
    应用场景:
    评论、弹幕、观众列表中的一条数据
②体系结构与术语

在这里插入图片描述
在这里插入图片描述

2.1.2 安装与连接

启动MongoDB

docker start mongo-service

mongoDB连接工具——studio3t安装
studio3t是MongoDB优秀的客户端工具。官方地址在https://studio3t.com/

2.1.3 Springboot整合MongoDB

①引入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
②添加服务端配置
server:
  port: 9998
spring:
  data:
    mongodb:
      host: 192.168.200.130
      port: 27017
      database: leadnews-comment
③准备实体类
/**
 * APP评论信息
 */
@Data
// 使用这个注解来映射实体类和集合的关系
@Document("ap_comment")
public class ApComment {
   

    /**
     * id
     */
    private String id;

    /**
     * 用户ID
     */
    private Integer userId;

    /**
     * 用户昵称
     */
    private String userName;

    /**
     * 文章id或动态id
     */
    private Long objectId;

    /**
     * 频道ID
     */
    private Integer channelId;

    /**
     * 评论内容类型
     * 0 文章
     * 1 动态
     */
    private Integer type;

    /**
     * 评论内容
     */
    private String content;

    /**
     * 作者头像
     */
    private String image;

    /**
     * 点赞数
     */
    private Integer likes;

    /**
     * 回复数
     */
    private Integer reply;

    /**
     * 文章标记
     * 0 普通评论
     * 1 热点评论
     * 2 推荐评论
     * 3 置顶评论
     * 4 精品评论
     * 5 大V 评论
     */
    private Integer flag;

    /**
     * 经度
     */
    private BigDecimal longitude;

    /**
     * 维度
     */
    private BigDecimal latitude;

    /**
     * 地理位置
     */
    private String address;

    /**
     * 评论排列序号
     */
    private Integer ord;

    /**
     * 创建时间
     */
    private Date createdTime;

    /**
     * 更新时间
     */
    private Date updatedTime;

}
④测试-新增
package com.itheima.mongo.test;

import com.itheima.mongo.pojo.ApComment;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Date;

/**
 * @author tp
 * @since 2024/2/19 13:24
 */

@SpringBootTest
@RunWith(SpringRunner.class)
public class MongoTest {
   

	@Autowired
	private MongoTemplate mongoTemplate;

	/**
	 * 测试新文档
	 */
	@Test
	public void testAddDocument() {
   
		for (int i = 1; i <= 10; i++) {
   
			ApComment apComment = new ApComment();
			apComment.setId(String.valueOf(i));// 评论id
			apComment.setUserId(i);// 评论用户id
			apComment.setUserName("测试用户"+i);// 评论用户名
			apComment.setType(0);// 内容类型,0表示文章类型
			apComment.setObjectId(Long.valueOf(10+i));//文章ID
			if (i % 2 == 0) {
   
				apComment.setFlag(1);// 热点评论
			} else {
   
				apComment.setFlag(0);// 普通评论
			}
			apComment.setContent("测试内容"+i);// 评论内容
			apComment.setLikes(100+i);// 点赞数
			apComment.setReply(0);// 回复数
			apComment.setCreatedTime(new Date());// 创建时间
			apComment.setUpdatedTime(new Date());// 创建时间
			// mongoTemplate.insert(apComment);// 仅表示新增文档
			mongoTemplate.save(apComment);// 表示新增文档或跟新文档
		}

	}
}

在测试的时候发现,MongoDB可以不创建数据库,可以不创建表,因为在运行的时候,会先读取配置的里database: leadnews-comment的值,发现数据库里没有这个数据库创建,同样的,读取@Document("ap_comment")里的值,发现没有这个集合就创建了这个集合。

⑤测试-查询
/**
	 * 测试查询
	 */
	@Test
	public void testQueryDocument() {
   
		System.out.println(mongoTemplate.findById("7", ApComment.class));
		Query query = Query.query(Criteria.where("userName").is("测试用户7"));
		System.out.println("----------------------------------------------");
		// 查询一条数据
		ApComment one = mongoTemplate.findOne(query, ApComment.class);
		System.out.println(one);

		System.out.println("-----------------------------------------------");

		// 查询的多条
		List<ApComment> all = mongoTemplate.findAll(ApComment.class);
		all.forEach(x-> System.out.println(x));
		System.out.println("-----------------------------------------------");

		// 查询列表数据:单条件条件查询
		List<ApComment> flag = mongoTemplate.find(Query.query(Criteria.where("flag").is(1)), ApComment.class);
		flag.forEach(x-> System.out.println(x));
		System.out.println("-----------------------------------------------");


		// 查询列表数据:多条件条件查询
		List<ApComment> flag1 = mongoTemplate.find(Query.query(Criteria.where("flag").is(1).and("likes").gt(102)), ApComment.class);
		flag1.forEach(x-> System.out.println(x));

		System.out.println("-----------------------------------------------");

		//查询列表数据:根据域进行排序和限制查询条数
		List<ApComment> apComments = mongoTemplate.find(Query.query(Criteria.where("flag").is(1).and("likes").gt(102)).with(Sort.by(Sort.Direction.DESC, "likes")).limit(3), ApComment.class);
		apComments.forEach(x-> System.out.println(x));

	}
⑥测试-更新

前两种常用,后一种有数字增减,可用

/**
	 * 测试更新文档
	 */
	@Test
	public void testUpdateDocument() {
   

		ApComment byId = mongoTemplate.findById("7", ApComment.class);
		byId.setContent("测试内容007");
		// 1. save
		mongoTemplate.save(byId);
		// 2. updateFirst(非线程安全的方法)
		mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(7)), Update.update("content", "修改的测试内容007"), ApComment.class);
		// 3. findAndModify(线程安全的方法)
		mongoTemplate.findAndModify(Query.query(Criteria.where("userId").is(7)), Update.update("content", "修改的测试内容007"), ApComment.class);
	}
测试-删除
/**
	 * 测试删除文档
	 */
	@Test
	public void testDeleteDocument() {
   
		// 1. 查询并删除
		// ApComment apComment = mongoTemplate.findById("7", ApComment.class);
		// mongoTemplate.remove(apComment);

		// 2. 根据条件删除
		mongoTemplate.remove(Query.query(Criteria.where("flag").is(1)), ApComment.class);
	}

2.2 app端评论-发表评论

2.2.1 需求分析

①需求分析

在这里插入图片描述

  • 文章详情页下方可以查看评论信息,按照点赞数量倒序排列,展示评论内容、评论的作者、点赞数、回复数、时间,默认查看10条评论,如果向查看更多,可以点击加载更多进行分页
  • 可以针对当前文章发布评论
  • 可以针对于某一条评论进行点赞操作
②对应数据存储结果-集合

APP评论信息
在这里插入图片描述
APP评论信息点赞
在这里插入图片描述
这两个集合是一对多的关系,表示一条评论可以让多个app用户点赞

2.2.2 接口定义

在这里插入图片描述

①实现步骤

1、搭建评论微服务
(1)创建项目heima-leadnews-comment
在这里插入图片描述
(2)bootstrap.yml
其中自动配置项去除了关于数据源的配置,因为这个项目不需要查询数据库,查询的mongodb
(3)nacos中添加comment的配置

spring:
  data:
    mongodb:
      host: 192.168.200.130
      port: 27017
      database: leadnews-comment

(4)启动类

@SpringBootApplication
@EnableDiscoveryClient
public class CommentApplication {
   

    public static void main(String[] args) {
   
        SpringApplication.run(CommentApplication.class,args);
    }
}

(5)添加WebMvcConfig

package com.heima.comment.config;

import com.heima.common.interceptor.TokenInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
   

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
   
         registry.addInterceptor(new TokenInterceptor()).addPathPatterns("/**")
                 //放行swagger和knife4j
                 .excludePathPatterns( "/v2/api-docs",
                         "/doc.html",
                         "/swagger-resources/configuration/ui",
                         "/swagger-resources",
                         "/swagger-resources/configuration/security",
                         "/swagger-ui.html",
                         "/webjars/**",
                         "/actuator/**");
    }
}

(6)接口定义
controller

@RestController
@RequestMapping("/api/v1/comment")
public class ApCommentController {
   

	/**
	 * 新增评论
	 * @return
	 */
	@PostMapping("/save")
	public ResponseResult save(@RequestBody CommentSaveDto dto) {
   
		return null;
	}
}

service

public interface ApCommentService{
   

	/**
	 * 新增评论
	 * @param dto
	 * @return
	 */
	ResponseResult save(CommentSaveDto dto);
}

2、实现思路
判断用户是否存在
判断文章是否存在
判断评论内容是否大于140字
安全过滤
保存评论

serviceImpl

@Service
public class ApCommentServiceImpl implements ApCommentService {
   
	@Autowired
	private IUserClient userClient;

	@Autowired
	private IArticleClient articleClient;

	@Autowired
	private MongoTemplate mongoTemplate;

	@Override
	public ResponseResult save(CommentSaveDto dto) {
   
		// 1. 判断参数是否为空
		if (dto.getArticleId()==null || StringUtils.isBlank(dto.getContent())){
   
			return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
		}
		// 2. 判断用户是否存在——调用user的feign接口(此feign接口一定要在user服务的webMvcConfig中放行)
		Integer userId = ThreadLocalUtil.getUserId();
		ApUser apUser = userClient.findOne(userId);
		if (apUser == null) {
   
			return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"APP用户不存在");
		}

		// 3. 判断文章是否存在
		ApArticle apArticle = articleClient.findOne(dto.getArticleId());
		if (apArticle == null) {
   
			return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章不存在");
		}

		// 4. 判断评论内容是否大于140字
		if (dto.getContent().length() > 140) {
   
			return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"内容长度超过140字");
		}
		// 5. 安全过滤(DFA审核和百度云文本审核)

		// 6. 保存评论到MongoDB中
		ApComment apComment = new ApComment();
		apComment.setUserId(userId);
		apComment.setUserName(apUser.getName());
		apComment.setImage(apUser.getImage());
		apComment.setType(0);	//评论的内容类型,0表示文章
		apComment.setObjectId(dto.getArticleId());
		apComment.setContent(dto.getContent());
		apComment.setLikes(0);
		apComment.setReply(0);
		apComment.setFlag(0);
		apComment.setCreatedTime(new Date());
		apComment.setUpdatedTime(new Date());

		mongoTemplate.save(apComment);
		return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
	}
}

3、配置网关
在这里插入图片描述

②用户远程接口-查询用户-接口定义

在这里插入图片描述

package com.heima.apis.user;

import com.heima.model.user.pojos.ApUser;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @author tp
 * @since 2024/2/19 16:17
 */

@FeignClient("leadnews-user")
public interface IUserClient {
   

	/**
	 * 根据id查询用户
	 * @param id
	 * @return
	 */
	@GetMapping("/api/v1/user/one/{id}")
	public ApUser findOne(@PathVariable("id") Integer id);
}

ApUserFeign

@FeignClient("leadnews-user")
public interface IUserClient {
   

	/**
	 * 根据id查询用户
	 * @param id
	 * @return
	 */
	@GetMapping("/api/v1/user/one/{id}")
	public ApUser findOne(@PathVariable("id") Integer id);
}
③长整型数据精度丢失问题

前端的问题
一旦遇到服务端响应的数据是长整型的,永远会把后两位,或者后三位变为0,所以服务端根本就不能返回长整型给前端
解决方法:
方案一:将文章的id的由long类型手动改为String类型,可以解决此问题。(需要修改表结构)pass掉
方案二:可以使用jackson进行序列化和反序列化解决

在这里插入图片描述

2.3 app端评论-点赞评论

2.3.1 需求分析

在这里插入图片描述

  • 用户点赞,可以增加点赞数量,点赞后不仅仅要增加点赞数,需要记录当前用户对于当前评论的数据记录
  • 用户取消点赞,点赞减一,更新点赞数据
    在这里插入图片描述

2.3.2 思路分析

在这里插入图片描述

2.3.3 接口定义

在这里插入图片描述

2.3.4 接口实现

package com.heima.comment.service.impl;

import com.heima.apis.article.IArticleClient;
import com.heima.apis.user.IUserClient;
import com.heima.comment.service.ApCommentService;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.common.ThreadLocalUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
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 java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author tp
 * @since 2024/2/19 16:06
 */

@Service
public class ApCommentServiceImpl implements ApCommentService {
   
	@Autowired
	private IUserClient userClient;

	@Autowired
	private IArticleClient articleClient;

	@Autowired
	private MongoTemplate mongoTemplate;

	@Override
	public ResponseResult save(CommentSaveDto dto) {
   
		// 1. 判断参数是否为空
		if (dto.getArticleId()==null || StringUtils.isBlank(dto.getContent())){
   
			return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
		}
		// 2. 判断用户是否存在——调用user的feign接口(此feign接口一定要在user服务的webMvcConfig中放行)
		Integer userId = ThreadLocalUtil.getUserId();
		ApUser apUser = userClient.findOne(userId);
		if (apUser == null) {
   
			return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"APP用户不存在");
		}

		// 3. 判断文章是否存在
		ApArticle apArticle = articleClient.findOne(dto.getArticleId());
		if (apArticle == null) {
   
			return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章不存在");
		}

		// 4. 判断评论内容是否大于140字
		if (dto.getContent().length() > 140) {
   
			return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"内容长度超过140字");
		}
		// 5. 安全过滤(DFA审核和百度云文本审核)

		// 6. 保存评论到MongoDB中
		ApComment apComment = new ApComment();
		apComment.setUserId(userId);
		apComment.setUserName(apUser.getName());
		apComment.setImage(apUser.getImage());
		apComment.setType(0);	//评论的内容类型,0表示文章
		apComment.setObjectId(dto.getArticleId());
		apComment.setContent(dto.getContent());
		apComment.setLikes(0);
		apComment.setReply(0);
		apComment.setFlag(0);
		apComment.setCreatedTime(new Date());
		apComment.setUpdatedTime(new Date());

		mongoTemplate.save(apComment);
		return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
	}

	/**
	 * 加载评论
	 * @param dto
	 * @return
	 */
	@Override
	public ResponseResult load(CommentDto dto) {
   

		return null;
	}

	/**
	 * 点赞评论或者取消点赞
	 * @param dto
	 * @return
	 */
	@Override
	public ResponseResult like(CommentLikeDto dto) {
   
		// 1. 判断参数是否为空
		if (StringUtils.isBlank(dto.getCommentId()) || dto.getOperation() == null) {
   
			return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
		}
		// 2. 判断评论是否存在
		ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
		if (apComment == null) {
   
			return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"评论不存在");
		}
		// 3. 查询评论对应的点赞记录
		// 根据评论id查询点赞记录
		ApCommentLike apCommentLike = mongoTemplate.findOne(Query.query(Criteria.where("userId").is(ThreadLocalUtil.getUserId()).and("commentId").is(dto.getCommentId())), ApCommentLike.class);
		// 3.1 点赞记录不存在如何处理?
		if (apCommentLike == null) {
   
			// 就是说还没有点过赞
			// 3.1.1 判断是否取消点赞
			if (dto.getOperation() == 1) {
   
				return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"点赞记录不存在,无法取消点赞");
			}
			// 3.1.2 更新评论的点赞数+1
			ApComment comment = mongoTemplate.findAndModify(Query.query(Criteria.where("id").is(dto.getCommentId())), new Update().inc("likes", 1).set("updateTime", new Date()), ApComment.class);
			// 3.1.3 保存点赞记录
			apCommentLike = new ApCommentLike();
			apCommentLike.setCommentId(dto.getCommentId());
			apCommentLike.setUserId(ThreadLocalUtil.getUserId());
			apCommentLike.setOperation(dto.getOperation());
			apCommentLike.setCreatedTime(new Date());
			apCommentLike.setUpdatedTime(new Date());
			mongoTemplate.save(apCommentLike);
		} else {
   
			// 3.2 点赞记录存在如何处理?
			// 3.2.1 判断是否重复点赞
			if (dto.getOperation() == 0 && apCommentLike.getOperation() == 0) {
   
				return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"不能重复点赞");
			}
			// 3.2.2 判断是否重复取消点赞
			if (dto.getOperation() == 1 && apCommentLike.getOperation() == 1) {
   
				return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"不能重复取消点赞");
			}
			// 3.2.3 如果操作的是点赞,则点赞数+1
			if (dto.getOperation() == 0) {
   
				mongoTemplate.findAndModify(Query.query(Criteria.where("id").is(dto.getCommentId())), new Update().inc("likes", 1).set("updateTime", new Date()), ApComment.class);
			} else {
   
				// 3.2.4 如果操作的是取消点赞,则点赞数-1
				mongoTemplate.findAndModify(Query.query(Criteria.where("id").is(dto.getCommentId())), new Update().inc("likes", -1).set("updateTime", new Date()), ApComment.class);
			}
			// 3.2.5 更新点赞记录的操作类型和时间
			apCommentLike.setOperation(dto.getOperation());
			apCommentLike.setUpdatedTime(new Date());
			mongoTemplate.save(apCommentLike);
		}
		// 4.查询最新点赞数并返回
		apComment = mongoTemplate.findById(dto.getCommentId(),ApComment.class);
		Map result = new HashMap();
		result.put("likes", apComment.getLikes());

		return ResponseResult.okResult(result);
	}
}

2.4 app端评论-评论列表

2.4.1 需求分析

查询评论列表,根据当前文章id进行检索,按照创建时间倒序,分页查询(默认10条数据)
在这里插入图片描述

2.4.2 接口定义

在这里插入图片描述

2.4.3 需求分析

在这里插入图片描述

2.4.4 接口实现

public ResponseResult load(CommentDto dto) {
   
		int size = 10; // 默认查询数
		// 1. 判断参数是否为空
		if (dto.getArticleId() == null || dto.getMinDate() == null) {
   
			return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
		}
		// 2. 根据条件查询评论列表(查询条件:type、objectId、createdTime 查询结果:createdTime倒序、限制查询10条)
		Query query = Query.query(Criteria
				.where("type").is(0)
				.and("objectId").is(dto.getArticleId())
				.and("createdTime").lt(dto.getMinDate()))
				.with(Sort.by(Sort.Direction.DESC, "createdTime"))
				.limit(size);
		List<ApComment> apCommentList = mongoTemplate.find(query, ApComment.class);
		// 3. 如果当前用户是游客,直接响应评论列表数据
		Integer userId = ThreadLocalUtil.getUserId();
		if (userId == 0) {
   
			return ResponseResult.okResult(apCommentList);
		}
		// 4. 如果当前用户是正常用户,需要标识评论列表中被当前用户点赞过的评论,再响应
		// 4.1 获取评论列表对应的评论ID列表
		List<String> commentIdList = apCommentList.stream().map(ApComment::getId).collect(Collectors.toList());
		// 4.2 查询当前用户针对当前评论列表对应的所有点赞记录(查询条件:userId,operation,commentId)
		Query queryCommentLike = query = Query.query(Criteria.where("userId").is(userId).and("operation").is(0).and("commentId").in(commentIdList));
		// 点赞记录列表
		List<ApCommentLike> apCommentLikes = mongoTemplate.find(queryCommentLike, ApCommentLike.class);

		// 4.3 在评论列表中找到被点赞过的评论并添加标识表示点赞过
		List<CommentVo> commentVoList = new ArrayList<>();
		for (ApComment apComment : apCommentList) {
   
			long count = apCommentLikes.stream().filter(x -> x.getCommentId().equals(apComment.getId())).count();
			CommentVo commentVo = new CommentVo();
			BeanUtils.copyProperties(apComment,commentVo);
			if (count > 0) {
   
				commentVo.setOperation(0);
			}
			commentVoList.add(commentVo);
		}
		return ResponseResult.okResult(commentVoList);
	}

2.5 app端评论回复-发表回复、点赞回复、回复列表

2.6 热点评论

2.6.1 需求分析

  • 一个文章最多有5条热点评论
  • 热点评论需要按照点赞数倒序排序
  • 前5条评论是按照点赞数倒序,其他按照时间倒序查询

实现思路-计算热点评论

在这里插入图片描述

相关推荐

  1. <span style='color:red;'>day</span><span style='color:red;'>09</span>

    day09

    2024-02-22 07:56:06      35 阅读
  2. MongoDB面试系列-03

    2024-02-22 07:56:06       27 阅读
  3. MongoDB面试系列-02

    2024-02-22 07:56:06       31 阅读
  4. <span style='color:red;'>Day</span>-<span style='color:red;'>02</span>-<span style='color:red;'>01</span>

    Day-02-01

    2024-02-22 07:56:06      38 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-22 07:56:06       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-22 07:56:06       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-22 07:56:06       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-22 07:56:06       18 阅读

热门阅读

  1. 机器学习是什么?

    2024-02-22 07:56:06       28 阅读
  2. http缓存?强制缓存和协商缓存?

    2024-02-22 07:56:06       27 阅读
  3. 利用System.Web.HttpRuntime.Cache制作缓存工具类

    2024-02-22 07:56:06       31 阅读
  4. 神经网络量化

    2024-02-22 07:56:06       29 阅读
  5. C语言K&R圣经笔记 8.1文件描述符 8.2低级IO

    2024-02-22 07:56:06       27 阅读
  6. Gson 库的使用

    2024-02-22 07:56:06       25 阅读
  7. Linux常见命令 | 文件传输命令scp

    2024-02-22 07:56:06       26 阅读
  8. [opencvsharp]将Mat转float数组

    2024-02-22 07:56:06       30 阅读
  9. CSS总结

    CSS总结

    2024-02-22 07:56:06      28 阅读
  10. scss导出颜色变量为空对象

    2024-02-22 07:56:06       28 阅读