按点赞数排序且数据不重复

探讨了在移动应用中,如何实现评论列表按点赞数和时间戳倒序分页加载,解决相同点赞数时避免重复加载的问题。采用分两步查询的方法,先加载相同点赞数的评论,再补充加载点赞数较低的评论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.背景

在移动端,评论列表要按点赞数倒序排序进行分页,如果点赞数相同按创建时间倒序排序。(倒序:值从大到小)

2.问题

以往列表需要按时间戳倒序排序,因为13位时间戳的唯一性强,不容易重复,可以取列表最后一个item的时间戳进行 < lastTime limit 20查询。防止因有新数据产生,而拉到上一页拉过的数据。

但是点赞数会出现相同的情况,比如有10个相等点赞数为5的数据,刚好分页到中间第五个,如何下一次分页的时候拉取剩下五个点赞数为5的和小于5的数据,避免拉到已经拉过的前五个数据呢?

3.解决方式

模仿时间戳分页。取最后一个item的点赞数(agreeCount)和创建时间戳(lastTime)。

数据排序规则为:先按点赞数倒序排序,如果点赞数相同按创建时间倒序排序。

伪sql:order by agreeCount desc,createTime desc.

第一页:不进行任何条件查询,直接按该顺序查出指定的条数比如前20条:limit 20。(如何判断是否为第一页,可跟移动端约定如:第一页agreeCount传-1,通过agreeCount == -1判断是否为第一页,切记不可以传0进行标识,因为点赞数会有为0的情况)。

第二页:分两步查询,(取问题2的例子)

  • 先拉取剩余相同点赞数的数据,因为当点赞数相同是按时间戳倒序排序的,所以可以通过 agreeCount = 5 and createTime < lastTime limit 20。然后判断数据是否满足页大小20,如果没有,进行第二步查询拉取小于5的点赞数数据进行填充。
  • 第二步,拉取小于5的点赞数数据,agreeCount < 5 limit (剩余个数) 。最后将两个list数据进行addAll即可,注意顺序不要乱了,点赞数相同的数据在前面,即点赞数相同list.addAll(小于当前点赞数list)。

最后附上完整的伪代码:

int pageSize = 20;
List<Ideas> list = new ArrayList();
if (agreeCount == -1){
//第一页
   list = (select * from t_ideas order by agreeCount desc,createTime desc limit pageSize);
} else {
//下一页
   //拉取等于当前点赞数数据
   List<Ideas> sameList = (
                      select * from t_ideas 
                     where agreeCount = 5 and createTime < lastTime 
                     order by agreeCount desc, createTime desc limit pageSize);
   list.addAll(sameList);

   if (sameList.size() < pageSize){
       //拉取少于当前点赞数数据
       int surplus = pageSize-sameList.size();
       List<Ideas> surPlusList = (
                     select * from t_ideas 
                     where agreeCount < 5 
                     order by agreeCount desc, createTime desc limit surplus);
       list.addAll(surPlusList);
  }

}

return list;

 

### 黑马评系统的功能实现 为了实现黑马评中的功能,可以通过 Redis 的 `Sorted Set` 数据结构来完成。以下是具体的实现方式: #### 1. 使用 Sorted Set 存储数据 Redis 中的 `Sorted Set` 是一种非常强大的数据结构,它仅可以存储唯一的成员(member),还可以为每个成员分配一个分(score)。这使得我们可以利用 `Sorted Set` 来记录用户的行为并按时间或其他条件排序。 当用户对某条笔记进行时,可以将该笔记 ID 和当前时间戳作为键值存入 `Sorted Set` 中。这样既能够保证的唯一性,又可以根据时间戳对记录进行排序[^3]。 ```python import redis # 初始化 Redis 连接 r = redis.StrictRedis(host='localhost', port=6379, db=0) def like_note(user_id, note_id): """ 用户对某个笔记进行的操作。 :param user_id: 用户的ID :param note_id: 被的笔记ID """ timestamp = int(time.time()) # 获取当前时间戳 # 将用户ID和笔记ID组合成唯一的key key = f"note:{note_id}:likes" # 添加到 Sorted Set 中,其中 score 为时间戳, member 为用户ID r.zadd(key, {user_id: timestamp}) ``` #### 2. 查询笔记的 通过查询 `Sorted Set` 的大小即可获取某条笔记的总量。 ```python def get_like_count(note_id): """ 获取某条笔记的。 :param note_id: 笔记ID :return: 总 """ key = f"note:{note_id}:likes" return r.zcard(key) # 返回集合中元素的量 ``` #### 3. 查看前 N 名者 如果需要展示最近的用户列表,可以直接从 `Sorted Set` 中提取排名靠前的数据。 ```python def get_top_likers(note_id, top_n=5): """ 获取某条笔记的TopN用户。 :param note_id: 笔记ID :param top_n: 需要返回的用户量,默认为5 :return: TopN者的用户ID列表 """ key = f"note:{note_id}:likes" return r.zrevrange(key, 0, top_n - 1) # 按照分值降序排列取前N个 ``` #### 4. 处理重复的情况 由于 `Sorted Set` 自动会过滤掉相同的成员,因此无需担心同一个用户的问题。每次调用 `zadd` 方法都会更新对应的分(即时间戳)[^2]。 --- ### 注意事项 - 如果遇到错误提示 `WRONGTYPE Operation against a key holding the wrong kind of value`,说明目标 Key 已经存在其类型是 `Sorted Set`。此时应先确认 Key 类型是否正确或者清理旧数据后再尝试操作。 - 时间戳的选择非常重要,在实际应用中可能还需要考虑毫秒级精度的时间戳以避免并发写入冲突。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值