1. 程式人生 > 程式設計 >Mongoose + Redis 讓分頁與排序共存

Mongoose + Redis 讓分頁與排序共存

序:

假期前,無心工作,心中只想為祖國母親慶生。摸魚也要有點意義:今天就來總結下前幾天在寫業務的時候遇到一個比較複雜的排序問題,記錄在這裡與大家分享。

1. 業務場景

由於涉及公司的一些內部業務,為避免一些奇奇怪怪的事情(你懂得)發生,我在這裡只寫下實現思路: 資料庫中的一些素材資訊需要後端查詢並返回展示,正常的類似這種查詢操作業務不是很難,這裡的需求有點不一樣: 首先:

  • 素材種類分為:
    • 預設素材(default:1為預設,0為正常)(預設唯一)
    • 普通素材(vip:0)
    • 會員素材(vip:1)
    • 使用者自定義的素材(可能是會員素材也可能是普通素材)(由於每個使用者自定義不一樣,在另外一張使用者自定義素材表:personal)

然後,每個使用者可以自定義一種素材作為自己的封面,產品爸爸對排序的要求是:素材列表支援分頁查詢,使用者每次請求返回這個素材列表的時候:如果使用者有自定義素材,優先返回,否則按照預設的順序返回,即: 當有自定義時:使用者自定義素材 > 預設素材 > 普通素材 > 會員素材 當無自定義時:預設素材 > 普通素材 > 會員素材

最後,素材的型別(預設、普通、會員)可在管理後臺設定,使用者自定義素材由使用者設定。

正文:

面對這樣一個排序功能,我一開始還是比較淡定的,心中竊喜:簡單!思路奉上: 查詢的時候用 Mongoosesort 排序,按照 ** default

逆序、vip 順序 的方式排列, 排好的list 就是:預設素材 > 普通素材 > 會員素材, 如果使用者有自定義設定,來一個二次查詢,把自定義素材**放到 list 最前面,由於使用者自定義的素材可能是預設、普通、會員,所以同時找到刪掉 list 中的自定義素材,這樣就確保自定義素材在 list 中只有一個, 排好的就是:使用者自定義素材 > 預設素材 > 普通素材 > 會員素材

但是,分頁怎麼做呢,用 limit + offset 這樣會出現一個問題,就是:

第一頁資料:01234 第二頁資料:56789 ...

這時候,A 使用者在瀏覽資料,瀏覽到第一頁時,B 使用者往第一頁資料插入一條:X

,此時此刻: A 使用者看到的資料:

第一頁資料:01234 第二頁資料:45678 ...

這樣就導致當使用者在分頁瀏覽資料時,有別的使用者插入資料,下一頁的第一條 是 上一頁的最後一條如果使用者的新增操作過多,會出現很多重複的資料

所以,對於分頁,我一般用的是 sid 分頁的方法(隨意找了一篇文章,我覺得 sid 的原理說清楚了,簡單就是)。

但是,既要用 sid 分頁,又要對所有素材排序,總讓人覺得有點矛盾。

說下最後採用的方法吧:

這裡多了管理後臺Redis 的操作: 在運營在管理後臺新增或者修改素材的時候,查詢一次資料庫,按照:預設 > 普通 > 會員 排序取出,以 有序集合 的資料型別將素材資料存入Redis

當使用者無自定義素材時,使用者每次獲取 list 查詢 Redis 就好

當使用者有自定義設定時候,獲取 list ,將自定義放到 0 分數位置,並刪除該素材在有序集合中的位置

此時sid 就是有序結合的每個元素的分數。

總結:

  1. 這樣做的好處是管理人員在設定的時候就將排好序的素材列表存入 Redis,不會出現分頁資料重複的情況
  2. 本質上:使用者每次只需要查 Redis, 根據使用者是否有自定義設定來做陣列元素的插入與刪除。

原文連結:segmentfault.com/a/119000002…