2013-04-17 6 views
2

Je suis en train d'effectuer une itération sur une collection (en exécutant Moped comme pilote Ruby) mais comment mettre à jour un champ pour chaque document?itération d'une collection dans MongoDB pour les mises à jour

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))} 

Cela ne met pas à jour le champ "âge", tandis qu'un

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

fait. Mais il ne semble pas très efficace d'itérer sur une collection et de rechercher l'identifiant dans chaque itération. Alors, comment pourrais-je simplifier cela? J'ai besoin d'un moyen rapide pour mettre à jour des millions de documents de cette façon.

Cordialement, Chris

+0

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

+0

@WiredPrairie qui définirait tous les documents au même âge (choisi au hasard). – Leopd

+0

@Leopd - true. Je me concentrais sur l'obtention de la syntaxe pour être efficace et tout en un appel. :) – WiredPrairie

Répondre

1

Vous traitez cyclomoteur plus comme il est MongoId. Le cyclomoteur n'est pas un ODM - c'est un pilote mongodb de bas niveau.

Lorsque vous itérez users.find vous obtenez une collection d'objets simples Moped::BSON::Document, qui ressemblent beaucoup plus à des objets ruby ​​Hash qu'autre chose. Donc, quand vous appelez update sur eux, vous êtes juste en train de mettre à jour le fichier local en mémoire et de ne pas toucher la base de données.

De même

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

est pas aussi mauvais que vous le pensez. Le cyclomoteur le compile en une seule commande update - il ne récupère pas le document, ne le modifie pas, puis le réécrit.

Pour la facilité de développement, vous serez probablement plus heureux réellement utiliser MongoId, comme ceci:

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

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

Mais si la performance est critique, d'un cyclomoteur est plus rapide. Vous pouvez également comparer le code officiel 10gen ruby driver. Si vous pouvez porter votre code en javascript, vous pouvez l'exécuter sur le serveur mongodb lui-même, ce qui éliminerait les retards réseau, mais faites attention de verrouiller toute la base de données pendant que vous faites de telles choses.

+0

Cela va toujours chercher chaque document et définir chaque document individuellement, n'est-ce pas? C'est juste une syntaxe différente. – WiredPrairie

+0

Il les récupère tous à la fois, ou au moins en gros lots. Il les réécrit un à la fois. – Leopd

+1

Salut et merci pour les réponses. La chose Moped vs Mongoid est: tout est sur la performance :) Je dois mettre à jour 8 millions de documents et Mongoid est 5-6 fois plus lent que la requête Moped plaine, même lorsque les validations sont sautées, c'est trop lent. Mais ma première approche fonctionne bien :) – ctp

Questions connexes