Column Down
select ja pluck ovat kaksi erilaista ja hyödyllistä tapaa palauttaa tietokantataulukon yhden tai useamman sarakkeen arvot kokoelmana. Kuvittele esimerkiksi, että tietokannassasi on questions-taulu. Jokaisessa question-sarakkeessa saattaa olla kolme kenttää: id, question_text ja foreign_key siihen liittyvästä taulusta. Jos haluat palauttaa vain question_text-sarakkeen arvot, käyttäisit select tai pluck. Haluaisin tutkia näiden kahden menetelmän eroja ja päätteeksi esitän pluck:n sovelluksen Rails-sovelluksen sisällä.
Select
select toimii kahdella ainutlaatuisella tavalla:
i.select ottaa lohkon ja toimii aivan kuten Array#select.
Model.all.select { |m| m.field == value }
Tämä muodostaa Ruby-objektien joukon tietokannasta soveltamisalaa varten, muuntaa ne joukoksi ja iteroi niiden läpi Array#select:n avulla.
selectvs.whereLohkon syöttäminen
select:iin, jossa on suuri tietomäärä (esim. monia rivejä) on hitaampaa kuin muiden strategioiden, kutenwhere:
Model.where(field: value), koska
Model.all.select { |m| m.field == value }:n avulla Rails muuntaa ensin kaikki taulukon rivit Ruby-objekteiksi ja ajaa sitten annetun lohkon kullekin Ruby-objektille, kun taasModel.where(field: value)luo SQL-lausekkeen, joka siirtää raskaan työn SQL:n tehtäväksi, joka on nopeampi kuin Ruby tämäntyyppisessä suodatuksessa.selectmuuttaa SQL-kyselynSELECT-lauseen niin, että vain tietyt kentät haetaan:Model.select(:field)
# =>Esimerkiksi eräästä projektistani:
Question.select(:question_text)
# => #<ActiveRecord::Relation >Tämä tuottaa seuraavan SQL:n:
SELECT "questions"."question_text" FROM "questions"Huomaa, että tässä jälkimmäisessä esimerkissä
select-metodi ei palauta matriisia, vaan ActiveRecord::Relation-olion. Tämän seurauksena voit ketjuttaa siihen muita ActiveRecord::QueryMethodeja. Esimerkiksi:Question.select(:question_text).limit(5)# => #<ActiveRecord::Relation >Tämä tuottaa seuraavan SQL:n:
SELECT "questions"."question_text" FROM "questions" LIMIT ? ]Pluck
Rails-oppaista:
pluckvoidaan käyttää yksittäisten tai useiden sarakkeiden kyselyyn mallin taustalla olevasta taulukosta. Se hyväksyy argumenttina listan sarakkeiden nimiä ja palauttaa määritettyjen sarakkeiden arvojen joukon vastaavalla tietotyypillä.Tärkeää tässä on se, että
pluckpalauttaa joukon. Se ei palauta ActiveRecord::Relation-oliota, kutenselect. Eli esimerkiksi:Question.pluck(:question_text)# => # this returns an array with all of the values from the question_text column from the questions table.Koska
pluckmuuntaa tietokantakyselyn tuloksen Ruby-massaksi rakentamattaActiveRecord-objektia, se on suorituskykyisempi kuinselect.Mutta se, että
pluckpalauttaa massan, tarkoittaa, että et voi ketjuttaa tavallisiaActiveRecord-kyselyitäpluck:n päälle. Se palauttaaNoMethodError:Question.pluck(:question_text).limit(5)# => NoMethodError: undefined method `limit' for #<Array:0x007fc5c1dfb3b0>Mutta
plucktoimiiActiveRecord-objekteilla, joten seuraava palauttaa odotetun tuloksen:Question.limit(5).pluck(:question_text)#=>
pluckvoi ottaa useita argumentteja muodostaakseen moniulotteisen joukon:Question.pluck(:question_text, :course_id)#=> , , ...]Milloin käyttäisin Pluckia ?
Olen käyttänyt
pluck:aActiveRecordmalliobjektien rajaamiseen määrittääkseni, mihin malliobjekteihin liittyy tietueita jossakin toisessa taulussa.Vastaanottakaamme esimerkiksi seuraava luokka:
class Appointment < ActiveRecord::Base
has_many :chargesendJos haluamme määrittää, millä
appointmentsonchargesja millä ei, voimme käyttääpluck:ascope:ssa. Näin menetellään:Aluksi on muistettava, että
Model.where(field: value):n kohdallavaluevoi olla joko yksittäinen objekti (kuteninteger,stringjne.) tai se voi ollaarrayobjektienarrayjoukko.Siten seuraava on kelvollinen ja palauttaa kaikki
appointments:t, joilla onidsja jotka sisältyvät joukkoon.Appointment.where(id: )# => returns all appointments with ids that are included in the arrayNyt tiedämme, että
pluckpalauttaa joukon, joten voimme muodostaa joukon, joka sisältää ne vieraat avaimet, jotka haluamme sisällyttää siihen liittyvään malliin. Jos esimerkiksi haluamme määrittää, mitkäappointmentsovat assosioituneetcharges:iin, voimme luoda matriisincharges-taulukonappointment_id-sarakkeesta seuraavasti:Charge.pluck(:appointment_id)# => returns an array with all of the appointment_ids from the charges table, like:Mitäksemme, mitkä
appointmentsovat assosioituneet maksuihin, voimme kirjoittaa:Appointment.where(id: Charge.pluck(:appointment_id))# this is the same as Appointment.where(id: )Ja muuntamalla tämä
Appointment-mallin laajuudeksi:class Appointment < ActiveRecord::Base
has_many :charges scope :received_payment_info, -> {
where(id: Charge.pluck(:appointment_id)) }endSiten nyt, kun haluamme määrittää, mihin
appointmentsliittyycharges, voimme kirjoittaa:Appointment.received_payment_info#=> #<ActiveRecord::Relationjoka tuottaa seuraavat SQL-kyselyt:
SELECT "charges"."appointment_id" FROM "charges"SELECT "appointments".* FROM "appointments" WHERE ("appointments"."id" IN (35, 44, 82) OR "appointments"."id" IS NULL)
plucksallii meidän:
- tehokkaasti kysyä assosioituneelta tietokantataululta…
- luoda assosioituneesta taulusta joukko, jossa on kaikki ensisijaisen taulun objektien vieraat_avaimet
- käyttää tuota joukkoa määrittääksemme, mitkä ensisijaisen taulun objektit ovat assosioituneita objekteja toissijaisessa taulussa
Toivon, että tästä oli apua. Nauti nyppimisestä ja valitsemisesta.