2017-08-29 3 views
0

Angenommen, ich habe ein Benutzermodell in meiner Datenbank, wobei Höhe und Gewicht jedes Benutzers bereits eingegeben wurden. Jetzt möchte ich eine BMI-Spalte in der Benutzertabelle hinzufügen, die aus dem Gewicht und der Höhe jedes vorhandenen Benutzers berechnet wird. Was wäre der effizienteste Weg, wenn ich eine Million Benutzer hätte?Rails Active Record - Erstellen einer Spalte aus anderen Spaltenwerten

P. S

Ich habe versucht, eine Schienen Route hinzufügen, die das Skript lokal ausgeführt wird, wenn sie aufgerufen, aber fand es zu lange dauert. Ich glaube nicht, dass ich die Rails-Konsole benutzen könnte, da es eine komplexe Methode erfordert.

+0

Haben Sie die Berechnung mit nur für migrierte Daten eine aktuelle Spalte in der Datenbank wollen, oder wollen Sie einfach nur ein Read-only-Attribut für das Modell? –

+0

Mögliches Duplikat von [Wie kann ich Aktualisierungen in Stapeln in Rails ausführen?] (Https://stackoverflow.com/questions/23252811/how-can-i-run-updates-in-batchs-in-rails) – Ilya

+0

@Ilya Definitiv nicht, dies erklärt, wie man Updates in Batches ausführt, ich wollte wissen, wie man eine Spalte basierend auf Werten aus anderen Spalten erstellt. –

Antwort

0

Zuerst müssen Sie eine Migration der Spalte hinzuzufügen, aber nicht setzen einen Standard (Standardeinstellung kann eine lange Zeit in Anspruch nehmen, wenn Sie eine Tonne Datensätze)

add_column: some_attribute,: string

Nachdem die Spalte vorhanden ist, müssen Sie sie erneut füllen.

Verwenden Sie find_each. 1.000.000 Benutzer benötigen etwas Zeit, um zu verarbeiten, egal was Sie tun. Die Verwendung von find_each stellt sicher, dass sie nur 1.000 gleichzeitig instanziiert werden.

User.find_each do |user| 
    num = user.height * user.width # or whatever you need to figure out here 
    user.update_attributes(some_attribute: num) 
end 

Sie könnten einen Endpunkt einrichten, der die find_each weg tritt, aber wirklich, du bist am besten dran es über die Konsole ausgeführt wird. Ich würde screen verwenden, da es das Potenzial hat, ein lang andauernder Prozess zu sein.

Sie könnten dies stattdessen in eine Migrationsdatei einfügen, aber es gibt unterschiedliche Meinungen darüber, ob es am besten ist, Daten in Migrationen zu manipulieren.

-1

Also, wenn Sie BMI zu jedem vorhandenen Benutzer hinzufügen möchten, vielleicht der beste Weg ist rake task zu erstellen, in dem Sie würde Logik zum Aktualisieren dieser Spalte hinzufügen.

Angenommen, Sie bereits neue Spalte bmi zu Benutzermodell hinzugefügt, die integer ist, dann sind Sie Rake Aufgabe benötigen:

namespace :user do 
    task :bmi_calculator => 'environment' do 
    User.find_each do |user| 
     bmi = user.height/user.weight (I'm not sure about computation) 
     user.update_attribute(bmi: bmi) 
    end 
    end 
end 

Dann können Sie diese Aufgabe ausführen (rake user:bmi_calculator), wann immer Sie wollen! Mein Rat ist auch, einen Cron-Job für diese Art von Aufgabe zu verwenden, um automatisch nach Mitternacht zu laufen, wenn der Verkehr nicht so groß ist.

Prost