2013-11-14 41 views
0

我有一個MongoDB的集合,命名爲玩家MongoDB的數據模型和更新策略

_id, name, stats[ { stName, stValue, stCountC } ] 

我會爲每個玩家每天可以更新各種統計數據,但是當發現一個新的值將只更新統計值(即,new.stCount > existing.stCountC)。我的一般想法是將每個唯一stName的統計數組限制爲2個對象 - 一個用於Current值,另一個用於Previous值。如果上面的查詢返回文檔

db.players.findOne({ name: "JSmith", 
        stats: { $elemMatch: { stName: "Avg", stCountC: 5 } } }) 

,然後我更新內容如下 - - 舉例因此,讓我們說我找到的6計數一個新的統計,我的查詢和更新過程將開始與

1)獲取jsmith的stValue其中stName = "Avg"stCountP = 4 -

db.players.findOne({ name: "JSmith", stats: { stName: "Avg", stCountP: 4 } }, 
        { stats.$.stValue }) 

2)插入此值到我的收藏StatsHistory,它擁有所有的歷史值,每個球員單個統計類型 -

db.statshistory.update({ Name: "JSmith", StatName: "Avg" }, 
         { $addToSet : { oldValues : { stValue: <val>, stCount: 4 } } }) 

3)更新我的收藏Players -

db.players.update({ Name: JSmith }, 
        { $push: { stats: { stName: "Avg", stValue: "98", stCountC: 6 } } 
        $pull: { stats: { stName: "Avg", stCountP: 4 } } }) 

db.players.update({ name: "JSmith", stats.stName: "Avg", stats.stCountC: 5 }, 
        { $rename: { "stats.stCountC": "stats.stCountP" } }) 

我會從玩家收集來呈現當前統計值的數據網格(即每個玩家一排,每名統計一列)。我還會看到顯示統計值趨勢的視圖,並假設我將使用MongoDB的聚合函數從StatsHistory集合中返回這些值。

問題:上面的數據模型和查找/更新過程是否合乎邏輯?

我很明顯是MongoDB的新手,所以對任何語法錯誤表示歉意,或者如果上述看起來完全不符合我的需求。任何反饋非常感謝!

解決: 感謝idbentley爲下面的建議。它幫助我使用async.js設計了以下數據庫更新過程。請注意,數據模型略有變化 - Players集合現在僅保存最新的統計值,每個嘗試更新通過更新主記錄上的LastScan日期戳,並且每個統計更新提供日期戳LastUpdate。統計數仍用於檢查返回的統計數據是否更新。這個程序還可以確保任何新玩家/統計數據都被插入到收藏中。

async.series([ 
    function(cb){ db.statshistory.update({ Name: <name>, StatName: <statname> }, 
             { $set : { LastScan: new Date() }}, 
             { upsert: true }, 
             function() { cb(); }); 
    } 
    ,function(cb){ db.statshistory.update({ Name: <name>, StatName: <statname>, OldValues: { $not : { $elemMatch : { StCount: <statcount> }}}}, 
             { $push : { OldValues: { LastUpdate: new Date(), StCount: <statcount>, StValue: <statvalue> }}}, 
             function() { cb(); }); 
    } 
    ,function(cb){ db.players.update({ Name: <name> }, 
            { $set : { LastScan: new Date() }}, 
            { upsert: true }, 
            function() { cb(); }); 
    } 
    ,function(cb){ db.players.update({ Name: <name> }, 
            { $pull : { Stats: { StName: <statname>, StCount: { $ne: <statcount> }}}}, 
            function() { cb(); }); 
    } 
    ,function(cb){ db.players.update({ Name: <name>, Stats: { $not : { $elemMatch : { StName: <statname>, StCount: <statcount> }}}}, 
            { $push : { Stats: { LastUpdate: new Date(), StCount: <statcount>, StValue: <statvalue> }}}, 
            function() { cb(); }); 
    }] 
    ,function() { console.log('update complete'); } 
) 

回答

1

我想你可能會讓事情變得更加複雜。

我你的要求的理解:

  1. 每個玩家都有一個編號,隨時間變化的統計數據。
  2. 我們應該保持的玩家一個完整的歷史統計一段時間,但多數情況下,我們只需要在當前和以前的統計

如果我理解正確的話,那麼我會稍微改變一些事情。

首先,我會給嵌入的stats文件添加一個current標誌。

那麼您的工作流程的變化:

db.statshistory.update({ Name: <name>, StatName: <statname> }, 
    { $addToSet : { oldValues : { <statobj> } } }); 

db.player.update({ Name: <name>, stats: 
    { $elemMatch: { stName: <statname>} } }, 
    { $pull: { current: false } }); 

db.player.update({Name: <name>, stats: 
    { $elemMatch: { stName: <statname>, current: true } } }, 
    { $set: { stats.current: false } }); 

db.player.update({Name: <name>}, 
    { $addToSet: { <statobj>, current: true } }); 

由於這種使用多個更新,它不會很好在多線程環境中工作。