Apa perbedaan antara Memetik dan Mengumpulkan di Rails?

123

Berikut dua contoh kode.

Yang pertama dengan collect:

User.first.gifts.collect(&:id)

Yang kedua dengan pluck:

User.first.gifts.pluck(:id)

Apakah ada perbedaan di antara mereka dalam performa atau hal lain?

Mohit Jain
sumber

Jawaban:

230

pluckberada di level db. Ini hanya akan menanyakan bidang tertentu. Lihat ini .

Saat kamu melakukan:

 User.first.gifts.collect(&:id)

Anda memiliki objek dengan semua bidang dimuat dan Anda cukup mendapatkan idterima kasih untuk metode berdasarkan Enumerable.

Begitu:

  • jika Anda hanya membutuhkan iddengan Rails 4, gunakan ids:User.first.gifts.ids

  • jika Anda hanya membutuhkan beberapa bidang dengan Rails 4, gunakan pluck:User.first.gifts.pluck(:id, :name, ...)

  • jika Anda hanya membutuhkan satu bidang dengan Rails 3, gunakan pluck:User.first.gifts.pluck(:id)

  • jika Anda membutuhkan semua bidang, gunakancollect

  • jika Anda membutuhkan beberapa bidang dengan Rails 4, tetap gunakan pluck

  • jika Anda membutuhkan beberapa bidang dengan Rails 3, gunakan selectdancollect

apneadiving
sumber
"jika Anda membutuhkan beberapa bidang, gunakan pilih dan kumpulkan" - tidak bisakah Anda menggunakan pluckdengan beberapa atribut, seperti pluck(:id, :name)?
Alexander
@AlexPopov - Rails 4+ mendukung pluckbanyak bidang, Rails 3 tidak, kecuali Anda menggunakan solusi Ryan Lefevre
marksiemers
3
Di Rails 4, jika Anda hanya membutuhkan id, gunakan .idsdokumen Ref: api.rubyonrails.org/classes/ActiveRecord/…
Ivan Chau
30

Iya. Menurut panduan Rails , plucklangsung mengubah hasil database menjadi array, tanpa membuat ActiveRecordobjek. Ini berarti kinerja yang lebih baik untuk kueri besar atau yang sering berjalan.

Selain jawaban @ apneadiving, pluckdapat menggunakan nama kolom tunggal dan ganda sebagai argumen:

Client.pluck(:id, :name)
# SELECT clients.id, clients.name FROM clients
# => [[1, 'David'], [2, 'Jeremy'], [3, 'Jose']]
Fellow Stranger
sumber
3

Perbedaan dasar dan utama adalah bahwa Memetik berlaku pada tingkat db dan mengumpulkan semua data dan kemudian mengembalikan catatan kepada Anda ketika Anda membutuhkan semua catatan menggunakan mengumpulkan dan ketika beberapa bidang kemudian menggunakan memetik

Thorin
sumber
2

Jika ada kasus di mana Anda menggunakan beberapa atribut dari rekaman yang diambil. Dalam kasus seperti itu, Anda harus menggunakan pluck.

User.collect(&:email)

Dalam contoh di atas jika Anda hanya membutuhkan atribut email daripada Anda membuang-buang memori dan waktu. Karena itu akan mengambil semua kolom dari tabel pengguna dalam database, mengalokasikan memori untuk setiap atribut (termasuk atribut yang tidak akan pernah Anda gunakan)

CATATAN: plucktidak mengembalikan ActiveRecord_Relation pengguna

Timpal Palden
sumber