2013-04-17 29 views
2

我正在遍历集合(运行Moped作为Ruby驱动程序),但如何为每个文档更新一个字段?在MongoDB中迭代集合以获取更新

irb> session = Moped::Session.new(["127.0.0.1:27017"]) 
irb> session.use :demoapp 
irb> users = session[:users] 
irb> users.find.each {|u| u.update(age: rand(18..80))} 

这不更新域 “年龄”,而一个简单的

irb> users.find.each {|u| users.find(_id: u["_id"]).update(age: rand(18..80))} 

一样。但是迭代一个集合似乎并不是非常有效,然后在每次迭代中查找id。那么我怎么能简化它呢?我需要一些快速的方法来以这种方式更新数百万个文档。

的问候, 克里斯

+0

'users.find.update_all(:$ set => {age:rand(18..80)}})'? – WiredPrairie

+0

@WiredPrairie会将所有文档设置为相同(随机选择)的年龄。 – Leopd

+0

@Leopd - true。我专注于让语法高效并且一次调用。 :) – WiredPrairie

回答

1

你更轻便摩托车治疗像它的mongoid。轻便摩托车不是一个ODM - 它是一个低级别的mongodb驱动程序。

当您迭代users.find时,您会收到一组简单的Moped::BSON::Document对象,这些对象比其他任何对象更像是ruby Hash对象。所以当你打电话给update时,你只是更新了内存中的本地设备而没有触及数据库。

同样

users.find(_id: u["_id"]).update(age: rand(18..80)) 

并不像你想象的那样糟糕。轻便摩托车将其编译为单个update命令 - 它不会获取文档,修改它,然后将其写回。

为了便于开发,你可能会更快乐实际使用mongoid,像这样:

class User 
    include Mongoid::Document 
    field :age, type: Integer 
end 

User.all.each do |u| 
    u.age = rand(18..80) 
    u.save! 
end 

但是如果性能是至关重要的,助力车速度更快。您也可以对官方10gen ruby driver进行基准测试。如果你可以将你的代码移植到javascript,你可以在mongodb服务器本身上运行它,这样可以消除网络延迟,但是在你做这些事情时要小心锁定整个数据库。

+0

这仍然会获取每个文档并单独设置每个文档,不是吗?这只是不同的语法。 – WiredPrairie

+0

它一次性提取它们,或者至少大批量提取它们。它一次写回一个。 – Leopd

+1

嗨,谢谢你的回复。 Moped与Mongoid的关系如下:它的性能都是:)我必须更新8百万个文档,而且Mongoid比简单的Moped查询慢5到6倍,即使验证被忽略时它太慢了。但我的第一种方法工作正常:) – ctp