2011-12-09 61 views
0

假設我有一組對象。我有另一個喜歡的集合,每個集合都由特定的用戶和特定的對象組成。因此,隨着時間的推移,通過用戶評分,每個對象具有可變數量的喜歡(全部大於0)。一種基於評分從集合中選擇選擇的算法?

我想從這個集合中選擇一個對象。應該更頻繁地選擇喜歡更多的對象,但有時候也會選擇喜歡低些的對象給它們一個機會。

我現在要記住的算法是,按照喜歡的順序排列對象,並生成一個隨機數,並使用數字來選擇一個範圍內的隨機對象。假設我有一百個對象,則選擇0-10的時間對象的50%被選中,10-15的時間的25%和15-100的時間的25%。

該算法的明顯問題是可伸縮性。當他們的1000000個對象,返回他們所有的陣列需要時間。有沒有人有更好的解決方案?數據庫是在MongoDB中實現的。

回答

1

我會反正規化一點,並添加一個'喜歡'計數器字段到被喜歡的對象。對象獲得喜歡時遞增,當對象不被喜歡時遞減。

db.test.insert({ 
    stuff: "likable stuff", 
    likes: 7 
}) 

然後我也有一個代表該對象是爲喜歡的結果鬥另一個領域。因此,例如,對象開始時這個字段設置爲「普通」,並且在有人獲得10個喜歡後,他們將成爲「精英」。 (或任何你想要的)當它們達到該閾值時更新它。這裏的想法是,在寫入過程中進行工作會使讀取操作更容易。

db.test.insert({ 
    stuff: "likable stuff", 
    likes: 7, 
    status: "ordinary/elite", 
}) 

好吧,現在選擇基於#of likes定義的組中的對象組很容易吧? db.collection.find({ status: 'elite' })

要在這些集合中隨機化文檔選擇,您可以隨機跳過一定數量的記錄,但這會導致可怕的性能並且無法擴展。

但是,您可以執行一個技巧,將隨機生成的數字存儲在文檔中。

讓我們插入這些傢伙一個到測試數據庫,並檢查了

db.test.insert({ 
    stuff: "likable stuff", 
    likes: 7, 
    status: "ordinary/elite", 
    random: Math.random() 
}) 

讓我們來看看文檔現在:

{ 
    stuff: "likable stuff", 
    likes: 7, 
    status: "ordinary/elite", 
    random: 0.9375813045563468 
} 

好,這裏是這個變得很酷。做一個findOne()查詢,其中狀態:精英 rand_num:$ gt {另一個隨機生成的數字btw 0和1}。

db.collection.find({ status: "elite", random: { "$gt": new_rand_num } })

如果findOne()查詢不返回結果,與$ LT再次這樣做,你一定會在方向中的至少一個找到的文件。

現在讓我們指出狀態和隨機。

db.collection.ensureIndex({ status: 1, random: 1} })

你覺得呢?

+0

什麼是'算法'?算法過去了'街道'? –

+0

米奇請... –

+1

我接受了你的建議,並用類似的列進行了非規範化處理。現在,我只是要使用skip方法,但是如果我看到數據增加和縮放問題,那麼隨機生成結果的方法似乎很棒! – MEURSAULT