MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Cambia il tipo di campo in Mongoid senza perdere dati

Ok ce l'ho fatta. Penso che ci sia un modo più veloce per usare la console mongo con qualcosa del genere:MongoDB:come modificare il tipo di campo?

Ma non riuscivo a far funzionare la conversione, quindi ho optato per questo metodo più lento nella console Rails con più tempi di inattività. Se qualcuno ha una soluzione più veloce per favore postala.

  • crea un nuovo campo Intero con un nuovo nome, ad esempio amount2
  • convertire ogni amount al valore corretto per amount2 in una console o in un'attività di 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

Nota che .all.each funziona bene (non è necessario utilizzare .find_each o .find_in_batches come il normale activerecord con mysql) a causa dei cursori mongodb. Non riempirà la memoria finché identity_map è disattivata.

  • disattiva il sito per la manutenzione, esegui la migrazione ancora una volta per acquisire eventuali campi di importo che potrebbero essere cambiati negli ultimi minuti (qualcosa come Transaction.where(:updated_at.gt => 1.hour.ago).each_with_index...

  • commenta field :amount, type: BigDecimal nel tuo modello, non vuoi più che mongoid conosca questo campo e spingi questo codice

  • ora esegui un altro script per rinominare la tua colonna (sovrascrive tutti i vecchi valori di stringa BigDecimal nel processo). Potrebbe essere necessario commentare tutte le convalide che hai sul modello che prevedono il vecchio campo.

Mongoid.identity_map_enabled = false
Transaction.all.each_with_index do |t,i|
  puts i if i%1000==0
  t.rename :amount2, :amount
end

Questo è atomico e non richiede un salvataggio sul modello.

  • aggiorna il tuo modello per riflettere il nuovo tipo di colonna field :amount, type: Integer
  • implementa e ripristina il sito

Come accennato, penso che ci sia un modo migliore, quindi se qualcuno ha qualche consiglio per favore condividi. Grazie!