2012-02-02 85 views
2

使用MongoDB和Ruby驱动程序,我试图计算我的应用中玩家的排名,所以我按照(在这种情况下)俯卧撑进行排序,然后添加一个排名字段和每个对象的值。MongoDB + Ruby:在迭代中更新记录

pushups = coll.find.sort(["pushups", -1]) 
pushups.each_with_index do |r, idx| 
    r[:pushups_rank] = idx + 1 
    coll.update({:id => r }, r, :upsert => true) 
    coll.save(r) 
end 

这种方法确实有效,但这是迭代对象并更新每个对象的最佳方法吗?有没有更好的方法来计算玩家的等级?

回答

3

另一种方法是通过执行一个javascript函数来完成服务器上的所有更新:

update_rank = "function(){ 
var rank=0; 
db.players.find().sort({pushups:-1}).forEach(function(p){ 
    rank +=1; 
    p.rank = rank; 
    db.players.save(p); 
}); 
}" 
cn.eval(update_rank) 

(代码假设你在蒙戈有一个“播放器”收集和可变cn红宝石是持有连接到您的数据库)

+0

我喜欢这种方法! – yalestar 2012-02-03 22:05:50

+0

我认为这也是正确的做法。请注意,使用带有$ set而不是保存的更新可能会更有效:db.players.update({_ id:p._id},{$ set:{rank:rank}})或其他东西 – 2012-02-04 00:26:58

+1

另请注意,eval锁整个数据库。这不会随着大量的并发请求和/或随着玩家的增长而扩展。 FWIW,我也在MongoDB中进行排名,并且将特定逻辑切换到Redis排序集。我写了一篇关于我的积极体验的文章:http://openmymind.net/2011/5/8/Practical-NoSQL-Solving-a-Real-Problem-w-Mongo-Red/ – 2012-02-04 00:29:57