Rails pluck - недокументированные возможности

Выбор колонки таблицы сразу в массив

Метод :pluck был представлен в Rails 3.2. Он позволяет производить выборку данных сразу в массив, минуя тяжелые объекты ActiveRecord. Даже если вы уже знаете что такое :pluck - уверен, вам будет, что узнать из этой статьи.

Rails до появления :pluck

Нам приходилось выбирать нужные объекты и потом маппить их массив. Минус такого подхода в том, что в промежуточном этапе нам нужно выделить память для массива объектов, что может довольно критически сказаться на производительности, если таких объектов много


User.select(:email)
  User Load (0.4ms)  SELECT "users"."email" FROM "users"
=> #, #, #]>

User.select(:email).map(&:email)
  User Load (0.4ms)  SELECT "users"."email" FROM "users"
=> ["bbb@bbb.bb", "vvv@vvv.vv", "aaa@aaa.aa"]

Pluck - выборка в массив быстрее и проще

В самой простой форме :pluck позволяет выбрать данные из колонки в массив, Однако в отличии от :select - он не строит инстансы ActiveRecord объектов, что значительно ускоряет скорость выборки и экономие памяти. У меня были случаи когда код через map работал 10 минут, а с pluck обрабатывался всего за минуту.


User.pluck(:email)
   (0.4ms)  SELECT "users"."email" FROM "users"
=> ["bbb@bbb.bb", "vvv@vvv.vv", "aaa@aaa.aa"]

Но, начиная с Rails 4 :pluck стал умнее и позволяет принимать более сложные парамеры


User.pluck(:email, :created_at)
   (0.5ms)  SELECT "users"."email", "users"."created_at" FROM "users"
=> 
Чего нет в документации!

В документации не написано, что pluck может также принимать SQL. Это позволит использовать его в более сложных случаях, Когда например, нужно выбрать значение из 2х таблиц. В принципе pluck и так это умеет, но только если выбирается столбец имеющий унакальное для 2х столбцов имя. С created_at так не болучится, Более того, возможно там понадобится выполнить какие-либо преобразования в процессе выборки и мы можем сделать их средаствами SQL


User.pluck(<<-PLUCK)
UPPER(email)
PLUCK
   (20.0ms)  SELECT UPPER(email)
 FROM "users"
=> ["BBB@BBB.BB", "VVV@VVV.VV", "AAA@AAA.AA"]
Выводы

pluck - простой и высокоэффективный метод маппинга данных из базы в массив, Он позволяет увеличить производительность в несколько раз и выполнить базовые преобразования средствами SQL

Что нужно помнить используя pluck?

  1. pluck вернет массив а не ActiveRecord::Relation, он должен быть последним в цепочке
  2. Всегда нужно помнить какие операции выполняются базой данных, а какие - ruby кодом. User.distinct.pluck(:emal) быстрее чем User.pluck(:email).uniq
  3. Pluck может производить выборку по нескольким полям User.pluck(:created_at, :email)
  4. Для простых преобразований или чтобы разрешить конфликт в имени столбца - можно передать запрос строкой User.joins(:projects).pluck(“projects.created_at”)
Комментарии