国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

MongoDB 如何實現實時排名

why_rookie / 2449人閱讀

摘要:總之,通過這樣的保存方式,我們能夠實現當學生成績改變時,快速簡單的修改數據庫記錄,而又能夠實時的查詢出新的排名了。

當我們將考試分數錄入系統時,會要對學生的分數進行一個排名,這個不困難。困難的是當學生的分數變更時,如何實時更新這些排名?

如果我們將排名保存為一個字段,那么意味著每次修改分數都會導致重新計算排名,以及更新數據庫中的排名字段值。這個計算量可大可小,極端的情況下,如果一個學生的分數從第一名變成 0(比如因為作弊而成績清零),那么所有學生的排名都有可能要改,這就導致大批量的數據庫 update 操作。

這種方式顯然是效率非常低的。那么這里給出一個解決辦法,能夠實現修改分數的同時,排名立刻得到更新,而無需大規模修改數據庫記錄。本文以 MongoDB 為例介紹如何保存這些分數。

假設我們有 10 個學生的考試成績分別為:

50 50 50 60 60 60 60 80 90 100

那么我可以創建一條排名記錄(假設這條記錄在集合 scores 里面),內容如下:

{
  key: "exam_001",
  scoreMap: [
    {score:50, count:3},
    {score:60, count:4},
    {score:80, count:1},
    {score:90, count:1},
    {score:100, count:1}
  ]
}

看到這里你就應該明白了,我保存的只是每個分數對應的人數。這樣當我需要添加一個 80 分的成績時,我只需將 {score:80, count:1} 改為 {score:80, count:2} 即可。

這種情況下如何獲得一個學生的排名呢?首先要說明,每個學生對應的分數并沒有保存在這里(你可以保存到另外的表里面,然后查出該學生的分數),這里保存的是分數的排名,而不是學生的排名。所以你查出分數后,對 scoreMap 數組中所有 score 大于該分數的元素的 count 值進行一個總和即可。

比如我想知道 85 分是第幾名,從數組中可以算知大于 85 分的人數為 2,那么 85 分自然是第 3 名了。

那么在 MongoDB 里面,可以這樣查詢:

db.scores.aggregate([
     {$match:{key:"exam_001"}},
     {$unwind:"$scoreMap"},
     {$match:{"scoreMap.score": {$gt: 85}}},
     {$group:{_id:0,count:{$sum:"$scoreMap.count"}}}
]);

查出來的結果為:

{ "_id" : 0, "count" : 2 }

這種保存方式有一個極大的好處,就是不論有多少學生參加排名,我的記錄數始終是有限的。假設這門考試總分 100 分,有 100 萬學生參加排名,那么極端情況下 scoreMap 數組中也只會有 201 個元素(0, 0.5, 1, ... 99.5, 100)。也就是說,它的值空間是非常有限的。

有人會進一步提出:如果我將班級平均分(帶兩位小數)也加入這樣的排名呢?值空間將會變成幾萬個,這樣的排名查詢起來豈不會很慢?

實際上不是這樣子的。雖然兩位小數使得值空間很大,但參與排名的班級非常有限,也就是說值的實際數量很小。如果是 100 個班級參與排名,不存在相同平均分的情況下, scoreMap 數組中也只有 100 個元素。所以計算排名絲毫不會慢下來。

如何更新

現在我們的排名已經不再是直接保存在數據庫,而是在查詢的時候算出來,那么當一個學生的成績變更時,我應該如何更新數據庫記錄呢?

當一個學生的成績從 a 變為 b 時,我們需要做兩個操作:

將成績為 a 的學生數量 -1;

將成績為 b 的學生數量 +1。

在 MongoDB 中,更新 scoreMap 數組元素的語句是這樣的:

給某個分數的人數加一的時候:

db.scores.update(
    {key:"exam_001", scoreMap:{$elemMatch:{score:99.5}}},
    {$inc:{"scoreMap.$.count":1}}
)

給某個分數的人數減一的時候:

db.scores.update(
    {key:"exam_001", scoreMap:{$elemMatch:{score:99.5,count:{$gt:0}}}},
    {$inc:{"scoreMap.$.count":-1}}
)

注意減一的時候,查詢條件加上了一個 count:{$gt:0} 的判斷,這是為了避免人數變成負數。

總之,通過這樣的保存方式,我們能夠實現當學生成績改變時,快速簡單的修改數據庫記錄,而又能夠實時的查詢出新的排名了。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/18816.html

相關文章

  • node.js中文資料導航

    摘要:中文資料導航官網七牛鏡像深入淺出系列進階必讀中文文檔被誤解的編寫實戰系列熱門模塊排行榜,方便找出你想要的模塊多線程,真正的非阻塞淺析的類利用編寫異步多線程的實例中與的區別管道拒絕服務漏洞高級編程業界新聞看如何評價他們的首次嘗鮮程序員如何說服 node.js中文資料導航 Node.js HomePage Node官網七牛鏡像 Infoq深入淺出Node.js系列(進階必讀) Nod...

    geekidentity 評論0 收藏0
  • Java爬蟲之爬取中國高校排名前100名并存入MongoDB

    摘要:介紹在博客爬蟲爬取中國高校排名前名并寫入中,我們利用來寫爬蟲,將中的大學排名表格爬取出來,并存入到中。本次分享將用的來實現相同的功能,并將爬取到的數據存入到數據庫中。 介紹 ??在博客:Python爬蟲——爬取中國高校排名前100名并寫入MySQL中,我們利用Python來寫爬蟲,將http://gaokao.xdf.cn/201702/1... 中的大學排名表格爬取出來,并存入到My...

    jzzlee 評論0 收藏0
  • Java爬蟲之爬取中國高校排名前100名并存入MongoDB

    摘要:介紹在博客爬蟲爬取中國高校排名前名并寫入中,我們利用來寫爬蟲,將中的大學排名表格爬取出來,并存入到中。本次分享將用的來實現相同的功能,并將爬取到的數據存入到數據庫中。 介紹 ??在博客:Python爬蟲——爬取中國高校排名前100名并寫入MySQL中,我們利用Python來寫爬蟲,將http://gaokao.xdf.cn/201702/1... 中的大學排名表格爬取出來,并存入到My...

    GeekQiaQia 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<