select und pluck sind zwei verschiedene und nützliche Möglichkeiten, die Werte einer oder mehrerer Spalten in einer Datenbanktabelle als Sammlung zurückzugeben. Stellen Sie sich zum Beispiel vor, Sie haben eine questions-Tabelle in Ihrer Datenbank. Jedes question könnte drei Felder haben: id, question_text und ein foreign_key aus einer zugehörigen Tabelle. Um nur die Werte aus der Spalte question_text zurückzugeben, würden Sie select oder pluck verwenden. Ich möchte die Unterschiede zwischen diesen beiden Methoden untersuchen und mit einer Anwendung von pluck innerhalb einer Rails-Anwendung enden.

Select

select funktioniert auf zwei verschiedene Arten:

i.select nimmt einen Block und funktioniert genau wie Array#select.

Model.all.select { |m| m.field == value }

Dies baut ein Array von Ruby-Objekten aus der Datenbank für den Bereich auf, konvertiert sie in ein Array und iteriert mit Array#select durch sie.

select vs where

Die Übergabe eines Blocks an select mit einem großen Datensatz (d.h. where:

Model.where(field: value)

Denn mit Model.all.select { |m| m.field == value } konvertiert Rails zuerst alle Tabellenzeilen in Ruby-Objekte und führt dann den gegebenen Block für jedes Ruby-Objekt aus, während Model.where(field: value) eine SQL-Anweisung generiert, die die schwere Arbeit auf SQL verlagert, was bei dieser Art von Filterung schneller ist als Ruby.

ii. select ändert die SELECT-Anweisung für die SQL-Abfrage so, dass nur bestimmte Felder abgerufen werden:

Model.select(:field)
# =>

Zum Beispiel aus einem Projekt von mir:

Question.select(:question_text)
# => #<ActiveRecord::Relation >

Dies erzeugt die folgende SQL-Anweisung:

SELECT "questions"."question_text" FROM "questions"

Bitte beachten Sie, dass in diesem zweiten Beispiel die select-Methode kein Array zurückgibt, sondern ein ActiveRecord::Relation-Objekt. Folglich können Sie andere ActiveRecord::QueryMethods mit ihr verketten. Zum Beispiel:

Question.select(:question_text).limit(5)# => #<ActiveRecord::Relation >

Dies erzeugt die folgende SQL:

SELECT "questions"."question_text" FROM "questions" LIMIT ? ]

Pluck

Aus den Rails Guides:

pluck kann verwendet werden, um einzelne oder mehrere Spalten aus der zugrunde liegenden Tabelle eines Modells abzufragen. Es akzeptiert eine Liste von Spaltennamen als Argument und gibt ein Array von Werten der angegebenen Spalten mit dem entsprechenden Datentyp zurück.

Der wichtige Punkt hier ist, dass pluck ein Array zurückgibt. Es gibt kein ActiveRecord::Relation Objekt zurück, wie select. Zum Beispiel:

Question.pluck(:question_text)# => # this returns an array with all of the values from the question_text column from the questions table.

Da pluck das Ergebnis einer Datenbankabfrage in ein Ruby-Array umwandelt, ohne ein ActiveRecord-Objekt zu erzeugen, ist es leistungsfähiger als select.

Dass pluck jedoch ein Array zurückgibt, bedeutet, dass Sie keine Standard-ActiveRecord-Abfragen mit pluck verketten können. Wenn Sie dies tun, erhalten Sie ein NoMethodError:

Question.pluck(:question_text).limit(5)# => NoMethodError: undefined method `limit' for #<Array:0x007fc5c1dfb3b0>

Aber pluck funktioniert mit ActiveRecord-Objekten, so dass die folgende Abfrage das erwartete Ergebnis liefert:

Question.limit(5).pluck(:question_text)#=> 

pluck kann mehrere Argumente annehmen, um ein mehrdimensionales Array zu erstellen:

Question.pluck(:question_text, :course_id)#=> , , ...]

Wann sollte ich Pluck verwenden?

Ich habe pluck verwendet, um ActiveRecord Modellobjekte zu erfassen, um festzustellen, welche Modellobjekte mit Datensätzen in einer anderen Tabelle verknüpft sind:

Nehmen wir zum Beispiel die folgende Klasse:

class Appointment < ActiveRecord::Base
has_many :chargesend

Wenn wir feststellen wollen, welche appointments charges haben und welche nicht, können wir pluck in einer scope verwenden. So geht’s:

Erinnern Sie sich zunächst daran, dass value bei Model.where(field: value) entweder ein einzelnes Objekt sein kann (wie integer, string usw.) oder ein array von Objekten.

Das Folgende ist also gültig und gibt alle appointments mit ids zurück, die im Array enthalten sind.

Appointment.where(id: )# => returns all appointments with ids that are included in the array

Wir wissen, dass pluck ein Array zurückgibt, also können wir ein Array konstruieren, das die Fremdschlüssel enthält, die wir im zugehörigen Modell erfassen wollen. Wenn wir zum Beispiel feststellen wollen, welche appointments mit charges verknüpft sind, können wir ein Array aus der Spalte appointment_id der Tabelle charges wie folgt erstellen:

Charge.pluck(:appointment_id)# => returns an array with all of the appointment_ids from the charges table, like: 

Um festzustellen, welche appointments mit Gebühren verknüpft sind, können wir schreiben:

Appointment.where(id: Charge.pluck(:appointment_id))# this is the same as Appointment.where(id: )

Und dies in einen Bereich des Modells Appointment umwandeln:

class Appointment < ActiveRecord::Base
has_many :charges scope :received_payment_info, -> {
where(id: Charge.pluck(:appointment_id)) }end

Wenn wir nun feststellen wollen, welche appointments mit charges verbunden sind, können wir schreiben:

Appointment.received_payment_info#=> #<ActiveRecord::Relation 

Was die folgenden SQL-Abfragen erzeugt:

SELECT "charges"."appointment_id" FROM "charges"SELECT "appointments".* FROM "appointments" WHERE ("appointments"."id" IN (35, 44, 82) OR "appointments"."id" IS NULL)

pluck erlaubt uns:

  1. eine assoziierte Datenbanktabelle effizient abzufragen, um…
  2. ein Array aus der assoziierten Tabelle mit allen foreign_keys von Objekten aus der primären Tabelle zu generieren
  3. das Array zu verwenden, um zu bestimmen, welche Objekte in der primären Tabelle assoziierte Objekte in der sekundären Tabelle haben

Ich hoffe, Sie fanden dies hilfreich. Viel Spaß beim Zupfen und Auswählen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.