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.

select vs where

Przekazanie bloku do select z dużym zestawem danych (tj. wieloma wierszami) jest wolniejsze niż użycie innych strategii, takich jak where:

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 gdy Model.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:

pluck moż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:

  1. wydajne odpytywanie stowarzyszonej tabeli bazy danych, aby…
  2. generować tablicę z tabeli stowarzyszonej zawierającą wszystkie klucze obce obiektów z tabeli podstawowej
  3. 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.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.