Mongoose + Redis 让分页与排序共存

序:

假期前,无意工做,心中只想为祖国母亲庆生。摸鱼也要有点意义:今天就来总结下前几天在写业务的时候遇到一个比较复杂的排序问题,记录在这里与你们分享。数据库

1. 业务场景

因为涉及公司的一些内部业务,为避免一些奇奇怪怪的事情(你懂得)发生,我在这里只写下实现思路: 数据库中的一些素材信息须要后端查询并返回展现,正常的相似这种查询操做业务不是很难,这里的需求有点不同: 首先:segmentfault

  • 素材种类分为:
    • 默认素材(default:1为默认,0为正常)(默认惟一)
    • 普通素材(vip:0)
    • 会员素材(vip:1)
    • 用户自定义的素材(多是会员素材也多是普通素材)(因为每一个用户自定义不同,在另一张用户自定义素材表:personal)

而后,每一个用户能够自定义一种素材做为本身的封面,产品爸爸对排序的要求是:素材列表支持分页查询,用户每次请求返回这个素材列表的时候:若是用户有自定义素材,优先返回,不然按照默认的顺序返回,即: 当有自定义时:用户自定义素材 > 默认素材 > 普通素材 > 会员素材 当无自定义时:默认素材 > 普通素材 > 会员素材后端

最后,素材的类型(默认、普通、会员)可在管理后台设置,用户自定义素材由用户设置。数组

正文:

面对这样一个排序功能,我一开始仍是比较淡定的,心中窃喜:简单!思路奉上: 查询的时候用 Mongoosesort 排序,按照 ** default 逆序、vip 顺序 的方式排列, 排好的list 就是:默认素材 > 普通素材 > 会员素材, 若是用户有自定义设置,来一个二次查询,把自定义素材**放到 list 最前面,因为用户自定义的素材多是默认、普通、会员,因此同时找到删掉 list 中的自定义素材,这样就确保自定义素材在 list 中只有一个, 排好的就是:用户自定义素材 > 默认素材 > 普通素材 > 会员素材code

可是,分页怎么作呢,用 limit + offset 这样会出现一个问题,就是:排序

第一页数据:01234 第二页数据:56789 ...ip

这时候,A 用户在浏览数据,浏览到第一页时,B 用户往第一页数据插入一条:X,此时此刻: A 用户看到的数据:get

第一页数据:01234 第二页数据:45678 ...产品

这样就致使当用户在分页浏览数据时,有别的用户插入数据,下一页的第一条 是 上一页的最后一条若是用户的添加操做过多,会出现不少重复的数据it

因此,对于分页,我通常用的是 sid 分页的方法(随意找了一篇文章,我以为 sid 的原理说清楚了,简单就是)。

可是,既要用 sid 分页,又要对全部素材排序,总让人以为有点矛盾。

说下最后采用的方法吧:

这里多了管理后台Redis 的操做: 在运营在管理后台添加或者修改素材的时候,查询一次数据库,按照:默认 > 普通 > 会员 排序取出,以 有序集合 的数据类型将素材数据存入Redis

当用户无自定义素材时,用户每次获取 list 查询 Redis 就好

当用户有自定义设置时候,获取 list ,将自定义放到 0 分数位置,并删除该素材在有序集合中的位置

此时sid 就是有序结合的每一个元素的分数。

总结:

  1. 这样作的好处是管理人员在设置的时候就将排好序的素材列表存入 Redis,不会出现分页数据重复的状况
  2. 本质上:用户每次只须要查 Redis, 根据用户是否有自定义设置来作数组元素的插入与删除。

原文连接:segmentfault.com/a/119000002…

相关文章
相关标签/搜索