淺嘗node-mongodb分頁實(shí)現(xiàn)

寫在前面

最近項(xiàng)目需使用mongoose分頁操作五垮,通過度娘發(fā)現(xiàn)扎附,很多都是直接用skip+limit實(shí)現(xiàn)分頁操作抠忘。但這樣做有個(gè)弊端撩炊,對(duì)于少量的數(shù)據(jù)來說,完全可行崎脉,當(dāng)數(shù)據(jù)量大了后拧咳,這種方案就不怎么可取了。因?yàn)閟kip需從頭開始查找囚灼,對(duì)于數(shù)據(jù)量大的數(shù)據(jù)庫骆膝,這樣的操作很費(fèi)時(shí)間。當(dāng)然對(duì)于mysql等數(shù)據(jù)庫來說灶体,分頁操作還有其他的實(shí)現(xiàn)方式阅签,但單就mongodb數(shù)據(jù)庫來說,有個(gè)簡單的優(yōu)化方式就是通過ObjectId來實(shí)現(xiàn)蝎抽。因?yàn)镺bjectId是可以比較大小的(不清楚的可自行查看ObjectId的構(gòu)成方式)愉择,因此我們可以操作gt,lt來優(yōu)化我們的分頁效果。為什么說這樣會(huì)快一點(diǎn)呢织中?這樣操作锥涕,我們的查找是從_id數(shù)據(jù)開始查詢,減少遍歷數(shù)據(jù)的時(shí)間狭吼。

實(shí)現(xiàn)原理

首先层坠,我們需要前端傳遞一個(gè)當(dāng)前頁數(shù)據(jù)的最后一個(gè)或第一個(gè)_id字段到服務(wù)器,服務(wù)器通過_id字段查找到數(shù)據(jù)所在位置刁笙,然后從當(dāng)前位置開始查找數(shù)據(jù)破花,如果是向后翻頁,那么我們向后查詢limit個(gè)數(shù)據(jù)出來疲吸,如果向前翻頁座每,我們向前查limit個(gè)數(shù)據(jù)出來。
整個(gè)原理其實(shí)應(yīng)該不是很難的摘悴,但是在實(shí)際操作過程中峭梳,有個(gè)很蛋疼的問題~~~

實(shí)現(xiàn)過程

當(dāng)我們想明白了原理后,開始用代碼實(shí)現(xiàn):
因?yàn)椴攘吮容^多的坑蹂喻,我就直接記錄下最后一次正確的思路葱椭,其他的,不如為外人道也(啰嗦)口四。首先我們說前端需要上傳的參數(shù)(如圖1所示):id(記錄的本組數(shù)據(jù)第一個(gè)id或最后一個(gè)id), preNum(當(dāng)前所在頁 from), nextNum(將要前往的頁 to), limit(每組數(shù)據(jù)的數(shù)據(jù)量 2)孵运,至于為什么傳遞這幾個(gè)參數(shù)?請(qǐng)看下文蔓彩。


圖1 前端上傳參數(shù)

假設(shè)數(shù)據(jù)庫中???5條數(shù)據(jù)治笨,編號(hào)為1-5驳概,前端分頁,每頁limit(2)條數(shù)據(jù)旷赖,那么我們的數(shù)據(jù)分組應(yīng)該是這樣的:

54,32,1

也就是說需要分三頁顺又,為什么說需要傳遞第一個(gè)數(shù)據(jù)的id或者最后一條數(shù)據(jù)的_id呢?因?yàn)樵谖覀儚牡谝豁撉袚Q到第二頁的時(shí)候杠愧,拿到編號(hào)為2的數(shù)據(jù)id開始向后查找,若相鄰頁數(shù)跳轉(zhuǎn)逞壁,就可直接向后拿到limit(2)條數(shù)據(jù)流济,也就是我們的34數(shù)據(jù)。當(dāng)然腌闯,如果是第一頁直接跳第三頁绳瘟,同理,我們可以直接從編號(hào)位2的數(shù)據(jù)開始向后跳過limit(2)條數(shù)據(jù)姿骏,然后拿到編號(hào)為5的數(shù)據(jù)糖声。正向跳轉(zhuǎn)解決完成。(ps:數(shù)據(jù)是反向獲取的分瘦,也就是最新的數(shù)據(jù)在最前面)
但是反向跳轉(zhuǎn)呢蘸泻?我們還是可以使用類似的思想來操作。但是要注意嘲玫,反向跳轉(zhuǎn)時(shí)悦施,我們需要獲取每組數(shù)據(jù)的第一條id數(shù)據(jù)!也就是說假如我們要從第三頁跳轉(zhuǎn)到第二頁去团,我們就可以從1開始查找比1的_id大的數(shù)據(jù)抡诞,那肯定會(huì)返回(5,4土陪,3昼汗,2)四條數(shù)據(jù),這個(gè)時(shí)候如果我們按照從大到小的順序排列鬼雀,我們的數(shù)據(jù)是這樣的:

1,54,32

和上面的數(shù)據(jù)比較會(huì)發(fā)現(xiàn)顷窒,想要從第三頁跳轉(zhuǎn)到第二頁需要先跳過54兩條數(shù)據(jù),也就是說如果數(shù)據(jù)多了源哩,其實(shí)還是從頭開始查詢的蹋肮,對(duì)我們的優(yōu)化不友好。然后我們按照從小到大的順序排列呢璧疗?數(shù)據(jù)是這樣的:

1,23,45

我們?cè)俸烷_始的數(shù)據(jù)對(duì)比坯辩,會(huì)發(fā)現(xiàn)我們的數(shù)據(jù)是反著的,我們想要的數(shù)據(jù)是:1崩侠,32漆魔,54。這個(gè)時(shí)候我想到了一個(gè)解決辦法:假設(shè)從第三頁跳轉(zhuǎn)第二頁。我們拿到從前端傳過來的每組數(shù)據(jù)的第一條_id字段改抡,這個(gè)時(shí)候我們拿到數(shù)據(jù)1的_id矢炼,然后向后查找limit(2)條數(shù)據(jù),這個(gè)時(shí)候?qū)⒎祷厍岸说臄?shù)據(jù)是23阿纤,這個(gè)時(shí)候我們可以在返回前做個(gè)處理句灌,將獲取到的數(shù)據(jù)重新按照從大到小的順序排列數(shù)據(jù),將數(shù)據(jù)變?yōu)?2欠拾,這個(gè)時(shí)候前端拿到的第一個(gè)數(shù)據(jù)就是3胰锌,符合我們的數(shù)據(jù)要求,當(dāng)從第二頁向第一頁切換時(shí)藐窄,我們拿到的將是數(shù)據(jù)3的_id字段资昧,重復(fù)前面的操作,從數(shù)據(jù)3的_id開始查找荆忍,會(huì)找到45兩條數(shù)據(jù)格带,返回前都經(jīng)過重新排序。當(dāng)然刹枉,如果是跳過多頁叽唱,我們就只需要計(jì)算從_id開始跳過相關(guān)數(shù)據(jù)就行了,這樣就會(huì)大大減小數(shù)據(jù)的查詢等操作(代碼實(shí)現(xiàn)請(qǐng)看圖2)微宝。


圖2 代碼實(shí)現(xiàn)

相關(guān)說明

  1. query對(duì)象是mongoose的方法尔觉,若使用mongodb類似,只需要將參數(shù)寫到find()內(nèi)就行
  2. ObjectId 重新排序是根據(jù)時(shí)間的高低重排芥吟≌焱可以看到其實(shí)_id字段其實(shí)是有時(shí)間戳在里面的,我們使用getTimestamp()方法就可以解析出每個(gè)_id的生成時(shí)間钟鸵。
收獲:

本次探究讓我更加深入的了解了mongodb做分頁時(shí)的過程钉稍,對(duì)于query參數(shù)的運(yùn)作有了深入的理解,而在數(shù)組排序方面棺耍,學(xué)習(xí)到了自定義字段排序的方法贡未,對(duì)數(shù)組排序有了更深入的了解。

ps:

以上內(nèi)容僅為自己的學(xué)習(xí)過程蒙袍,歡迎大家取其精華俊卤,丟其糟粕。若對(duì)以上內(nèi)容有不同理解或更好的想法害幅,歡迎一起探討消恍。
企鵝號(hào):1041415167 郵箱地址:zth1041415167@outlook.com

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市以现,隨后出現(xiàn)的幾起案子狠怨,更是在濱河造成了極大的恐慌约啊,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佣赖,死亡現(xiàn)場(chǎng)離奇詭異恰矩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)憎蛤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門外傅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人俩檬,你說我怎么就攤上這事萎胰。” “怎么了豆胸?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵奥洼,是天一觀的道長巷疼。 經(jīng)常有香客問我晚胡,道長,這世上最難降的妖魔是什么嚼沿? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任估盘,我火速辦了婚禮,結(jié)果婚禮上骡尽,老公的妹妹穿的比我還像新娘遣妥。我一直安慰自己,他們只是感情好攀细,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布箫踩。 她就那樣靜靜地躺著,像睡著了一般谭贪。 火紅的嫁衣襯著肌膚如雪境钟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天俭识,我揣著相機(jī)與錄音慨削,去河邊找鬼。 笑死套媚,一個(gè)胖子當(dāng)著我的面吹牛缚态,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播堤瘤,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼玫芦,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了本辐?” 一聲冷哼從身側(cè)響起姨俩,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤蘸拔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后环葵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體调窍,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年张遭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了邓萨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡菊卷,死狀恐怖缔恳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情洁闰,我是刑警寧澤歉甚,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站扑眉,受9級(jí)特大地震影響纸泄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜腰素,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一聘裁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧弓千,春花似錦衡便、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至姻政,卻和暖如春呆抑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背扶歪。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來泰國打工理肺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人善镰。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓妹萨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親炫欺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子乎完,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容