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;