Players という名前の MongoDB コレクションがあります
_id, name, stats[ { stName, stValue, stCountC } ]
各プレイヤーのさまざまな統計を毎日更新しますが、新しい値が見つかった場合にのみ統計値を更新します (つまり、new.stCount > existing.stCountC
)。私の一般的な考えは、統計配列を一意ごとに 2 つのオブジェクトに制限することですstName
。1 つは現在の値用で、もう 1 つは以前の値用です。したがって、たとえば、カウントが 6 の新しい統計を見つけたとします。クエリと更新プロセスは次のように開始されます。
db.players.findOne({ name: "JSmith",
stats: { $elemMatch: { stName: "Avg", stCountC: 5 } } })
上記のクエリがドキュメントを返す場合、次のように更新します -
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 } } })
Players
3)コレクションを更新する -
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" } })
Players コレクションの現在の統計値のデータ グリッドを表示します (つまり、プレーヤーごとに 1 行、統計名ごとに 1 列)。統計値の傾向を示すビューも用意し、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'); }
)