Column Down
select i pluck są dwoma różnymi i użytecznymi sposobami zwracania wartości z jednej lub więcej kolumn w tabeli bazy danych jako kolekcji. Na przykład, wyobraź sobie, że masz tabelę questions w swojej bazie danych. Każda question może mieć trzy pola: id, question_text, oraz foreign_key z powiązanej tabeli. Aby zwrócić wartości tylko z kolumny question_text, użyłbyś select lub pluck. Chciałbym zbadać różnice między tymi dwiema metodami i zakończyć zastosowaniem pluck wewnątrz aplikacji Rails.
Select
select działa na dwa unikalne sposoby:
i.select przyjmuje blok i działa tak samo jak Array#select.
Model.all.select { |m| m.field == value }
Buduje tablicę obiektów Ruby z bazy danych dla zakresu, konwertując je na tablicę i iterując przez nie za pomocą Array#select.
selectvswherePrzekazanie bloku do
selectz dużym zestawem danych (tj. wieloma wierszami) jest wolniejsze niż użycie innych strategii, takich jakwhere:
Model.where(field: value)ponieważ w przypadku
Model.all.select { |m| m.field == value }, Railsy najpierw przekonwertują wszystkie wiersze tabeli na obiekty Ruby, a następnie uruchomią dany blok dla każdego obiektu Ruby, podczas gdyModel.where(field: value)generuje instrukcję SQL, która odciąża SQL, który jest szybszy niż Ruby dla tego typu filtrowania.
ii. select modyfikuje instrukcję SELECT dla zapytania SQL tak, że tylko niektóre pola są pobierane:
Model.select(:field)
# =>
Na przykład, z mojego projektu:
Question.select(:question_text)
# => #<ActiveRecord::Relation >
To generuje następujący SQL:
SELECT "questions"."question_text" FROM "questions"
Zauważ, że w tym drugim przykładzie, metoda select nie zwraca tablicy; zwraca obiekt ActiveRecord::Relation. W rezultacie, można do niej podłączyć inne metody ActiveRecord::QueryMethods. Na przykład:
Question.select(:question_text).limit(5)# => #<ActiveRecord::Relation >
Generuje to następujący SQL:
SELECT "questions"."question_text" FROM "questions" LIMIT ? ]
Pluck
Z przewodnika po Railsach:
pluckmoże być użyty do zapytania o pojedyncze lub wiele kolumn z bazowej tabeli modelu. Przyjmuje listę nazw kolumn jako argument i zwraca tablicę wartości określonych kolumn z odpowiadającym im typem danych.
Ważnym punktem jest to, że pluck zwraca tablicę. Nie zwraca on obiektu ActiveRecord::Relation, jak select. Tak więc, na przykład:
Question.pluck(:question_text)# => # this returns an array with all of the values from the question_text column from the questions table.
Ponieważ pluck przekształca wynik zapytania do bazy danych w tablicę Ruby bez konstruowania obiektu ActiveRecord, jest bardziej wydajne niż select.
Jednakże fakt, że pluck zwraca tablicę oznacza, że nie można łączyć standardowych zapytań ActiveRecord z pluck. Takie zapytanie zwróci NoMethodError:
Question.pluck(:question_text).limit(5)# => NoMethodError: undefined method `limit' for #<Array:0x007fc5c1dfb3b0>
Ale pluck działa na obiektach ActiveRecord, więc poniższe zapytanie zwróci oczekiwany wynik:
Question.limit(5).pluck(:question_text)#=>
pluck może przyjmować wiele argumentów, aby skonstruować wielowymiarową tablicę:
Question.pluck(:question_text, :course_id)#=> , , ...]
Kiedy użyłbym Pluck?
Użyłem pluck do zakresu ActiveRecord obiektów modelu, aby określić, które obiekty modelu mają powiązane rekordy w innej tabeli.
Na przykład weźmy następującą klasę:
class Appointment < ActiveRecord::Base
has_many :chargesend
Jeśli chcemy określić, które appointments mają charges, a które nie, możemy użyć pluck w scope. Oto jak:
Po pierwsze, pamiętaj, że dla Model.where(field: value), value może być albo pojedynczym obiektem (jak integer, string, itd.), albo może być array obiektów.
Więc, poniższe jest ważne i zwróci wszystkie appointments z ids, które są zawarte w tablicy.
Appointment.where(id: )# => returns all appointments with ids that are included in the array
Wiemy, że pluck zwraca tablicę, więc możemy skonstruować tablicę, która zawiera klucze obce, które chcemy określić w powiązanym modelu. Na przykład, jeśli chcemy określić, które appointments mają powiązane charges, możemy utworzyć tablicę z kolumny appointment_id tabeli charges, tak jak to:
Charge.pluck(:appointment_id)# => returns an array with all of the appointment_ids from the charges table, like:
Aby określić, które appointments mają powiązane opłaty, możemy napisać:
Appointment.where(id: Charge.pluck(:appointment_id))# this is the same as Appointment.where(id: )
A przekształcając to w zakres na modelu Appointment:
class Appointment < ActiveRecord::Base
has_many :charges scope :received_payment_info, -> {
where(id: Charge.pluck(:appointment_id)) }end
Teraz więc, gdy chcemy określić, które appointments mają powiązane charges, możemy napisać:
Appointment.received_payment_info#=> #<ActiveRecord::Relation
, co generuje następujące zapytania SQL:
SELECT "charges"."appointment_id" FROM "charges"SELECT "appointments".* FROM "appointments" WHERE ("appointments"."id" IN (35, 44, 82) OR "appointments"."id" IS NULL)
pluck pozwoliło nam na:
- wydajne odpytywanie stowarzyszonej tabeli bazy danych, aby…
- generować tablicę z tabeli stowarzyszonej zawierającą wszystkie klucze obce obiektów z tabeli podstawowej
- wykorzystać tę tablicę do określenia, które obiekty w tabeli podstawowej mają powiązane obiekty w tabeli drugorzędnej
Mam nadzieję, że uznałeś to za pomocne. Ciesz się skubaniem i wybieraniem.