wake-up-neo.com

Stapeleinsatz in Schienen 3

Ich möchte aus meiner Rails-App einen Stapeleintrag von wenigen tausend Datensätzen in die Datenbank (in meinem Fall POSTGRES) durchführen.

Was wäre der "Rails-Weg", um dies zu tun? Etwas, das schnell und auch richtig ist.

Ich weiß, dass ich die SQL-Abfrage durch eine Zeichenfolgenverkettung der Attribute erstellen kann, aber ich möchte einen besseren Ansatz.

36
phoenixwizard

Die ActiveRecord .create - Methode unterstützt die Massenerstellung. Die Methode emuliert das Feature, wenn die Datenbank es nicht unterstützt, und verwendet das zugrunde liegende DB-Modul, falls das Feature unterstützt wird.

Übergeben Sie einfach eine Reihe von Optionen.

# Create an Array of new objects
User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])

Block wird unterstützt und ist der übliche Weg für gemeinsam genutzte Attribute.

# Creating an Array of new objects using a block, where the block is executed for each object:
User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u|
  u.is_admin = false
end
55
Simone Carletti

Nach den beiden Antworten von @Simone Carletti und @Sumit Munot habe ich endlich eine Lösung gefunden.

Bis der Postgres-Treiber die Masseneinfügung der ActiveRecord .create-Methode unterstützt, möchte ich mit activerecord-import gem gehen. Es fügt Masseneinfügung und auch das in einer einzigen Einfügeanweisung ein.

books = []
10.times do |i| 
    books << Book.new(:name => "book #{i}")
end
Book.import books

In POSTGRES führt es zu einer einzigen Insert-Status.

Wenn der Postgres-Treiber die Masseneinfügung der Methode ActiveRecord .create in einer einzigen Einfügeanweisung unterstützt, ist die Lösung von @Simone Carletti sinnvoller :)

20
phoenixwizard

Sie können ein Skript in Ihrem Rails-Modell erstellen und Ihre Abfragen zum Einfügen in dieses Skript schreiben. In Rails können Sie das Skript mit ausführen

Rails runner MyModelName.my_method_name

Ist der beste Weg, den ich in meinem Projekt verwendet habe.

Update:

Ich verwende folgendes in meinem Projekt, aber es ist nicht richtig für die SQL-Injektion. Wenn Sie keine Benutzereingaben in dieser Abfrage verwenden, kann dies für Sie funktionieren

user_string = " ('[email protected]','a'), ('[email protected]','b')"
User.connection.insert("INSERT INTO users (email, name) VALUES"+user_string)

Für mehrere Datensätze:  

new_records = [
  {:column => 'value', :column2 => 'value'}, 
  {:column => 'value', :column2 => 'value'}
]

MyModel.create(new_records)
2
Sumit Munot

Das geht auf die schnelle oder auf die Rails-Weise;) Der beste Weg, um Bulk-Daten in Postgres zu importieren, ist meiner Meinung nach der CSV. Was einige Zeit dauert, dauert der Rails-Weg mit der nativen CSV-Importfunktion von Postgres einige Sekunden.

http://www.postgresql.org/docs/9.2/static/sql-copy.html

Es löst sogar Datenbankauslöser aus und respektiert Datenbankeinschränkungen.

Bearbeiten Sie (nach Ihrem Kommentar): Gotcha. In diesem Fall haben Sie Ihre beiden Optionen richtig beschrieben. Ich war schon in der gleichen Situation, habe es mit den Rails 1000 sparen! Strategie, weil dies die einfachste Sache war, die funktioniert hat, und dann für die Strategie "Anhängen einer großen Abfragezeichenfolge" optimiert wurde, da sie um eine Größenordnung besser war.

Natürlich ist die vorzeitige Optimierung die Wurzel allen Übels, also machen Sie es vielleicht auf die einfache, langsame Rails-Art, und wissen Sie, dass das Erstellen einer großen Abfragezeichenfolge eine absolut legitime Methode zur Optimierung auf Kosten der Wartung ist. Ich glaube, Ihre eigentliche Frage lautet "Gibt es einen Railsy-Weg, der nicht Tausende von Abfragen umfasst?" - Die Antwort darauf ist leider nein.

0
Chris Aitchison