我有一个名为 Players 的 MongoDB 集合
_id, name, stats[ { stName, stValue, stCountC } ]
我将每天更新每个玩家的各种统计数据,但只会在找到新值时更新统计值(即new.stCount > existing.stCountC
)。我的一般想法是将 stats 数组限制为每个唯一的 2 个对象stName
——一个用于当前值,一个用于上一个值。因此,举例来说,假设我找到一个计数为 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 } } })
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" } })
我将展示来自 Players 集合的当前统计值的数据网格(即每个玩家一行,每个统计名称一列)。我还将有显示统计值趋势的视图,并假设我将使用 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'); }
)