Ok j'ai réussi. Je pense qu'il existe un moyen plus rapide d'utiliser la console mongo avec quelque chose comme ceci :MongoDB :Comment changer le type d'un champ ?
Mais je n'ai pas pu faire fonctionner la conversion, j'ai donc opté pour cette méthode plus lente dans la console des rails avec plus de temps d'arrêt. Si quelqu'un a une solution plus rapide, merci de la publier.
- créer un nouveau champ Integer avec un nouveau nom, par exemple
amount2
- convertir chaque
amount
à la bonne valeur pouramount2
dans une tâche console ou rake
Mongoid.identity_map_enabled = false
Transaction.all.each_with_index do |t,i|
puts i if i%1000==0
t.amount2 = t.amount.to_money
break if !t.save
end
Notez que .all.each fonctionne bien (vous n'avez pas besoin d'utiliser .find_each ou .find_in_batches comme activerecord normal avec mysql) à cause des curseurs mongodb. Il ne remplira pas la mémoire tant que l'identity_map est désactivé.
-
arrêtez le site pour maintenance, exécutez la migration une fois de plus pour capturer tous les champs de montant qui auraient pu changer au cours des dernières minutes (quelque chose comme
Transaction.where(:updated_at.gt => 1.hour.ago).each_with_index...
-
commentez le
field :amount, type: BigDecimal
dans votre modèle, vous ne voulez plus que mongoid connaisse ce champ, et poussez ce code - exécutez maintenant un autre script pour renommer votre colonne (il écrase toutes les anciennes valeurs de chaîne BigDecimal dans le processus). Vous devrez peut-être commenter toutes les validations que vous avez sur le modèle qui attendent l'ancien champ.
Mongoid.identity_map_enabled = false
Transaction.all.each_with_index do |t,i|
puts i if i%1000==0
t.rename :amount2, :amount
end
Ceci est atomique et ne nécessite pas de sauvegarde sur le modèle.
- mettez à jour votre modèle pour refléter le nouveau type de colonne
field :amount, type: Integer
- déployer et remettre le site en ligne
Comme mentionné, je pense qu'il existe un meilleur moyen, donc si quelqu'un a des conseils, merci de les partager. Merci !