ActiveRecord выбрать атрибуты без объектов AR - PullRequest
2 голосов
/ 18 февраля 2010

У меня есть таблица с МНОГИМИ строками, мне нужны только идентификаторы определенных строк.Медленный способ - вызвать

SomeARClass.find(:all, :conditions => {:foo => true}, :select => :id)

. Это возвращает объекты AR ...

. Есть ли способ вызвать select для класса и вернуть ему старую структуру данных ruby.Как то так:

SomeARClass.select(:id, :conditions => {:foo => true})
-> [1,2,3]

Ответы [ 4 ]

5 голосов
/ 19 февраля 2010
ActiveRecord::Base.connection.select_all(sql)

или

SomeARClass.connection.select_all(sql)

Это то, что вы хотите использовать. Возвращает массив хэшей. Это должно использоваться экономно, хотя. Закодированный вручную sql - это то, что ActiveRecord было создано для замены. Я использую только в действительно критических областях производительности, где создание и возврат объектов AR слишком медленный.

3 голосов
/ 30 октября 2013

Метод pluck - это именно то, что вам нужно, без ущерба для плохой практики SQL:

SomeARClass.where(:foo => true).pluck(:id)

Я считаю, что это должен быть выбранный ответ!

3 голосов
/ 18 февраля 2010

Я не думаю, что есть что-то вроде SomeARClass.select(:id, :conditions => {:foo => true}) , но у вас есть два варианта

  1. SomeARClass.find(:all, :conditions => {:foo => true}, :select => :id).map(&:id)
    #=> [1,2,3,4]
    
  2. id_hash = ActiveRecord::Base.connection.select_all('select id from tablename')
    #=>  [{"id"=>"1"}, {"id"=>"2"}, {"id"=>"3"}, {"id"=>"4"}]
    
    id_hash.map(&:values).flatten
    #=>  ["1", "2", "3", "4"]
    

Второй параметр возвращает только хэш, а не объекты активной записи, но выглядит немного хакерским.

0 голосов
/ 01 октября 2018

Краткий ответ:

  • Используйте .ids для получения только идентификаторов
  • Используйте pluck для выборки ТОЛЬКО некоторых столбцов, но значения будут ПАРСИРОВАНЫ активной записью
  • Используйте ActiveRecord::Base.connection.select_all, чтобы получить НЕПАРСИНДИРОВАННЫЕ значения.

Примечания:

Существует небольшая разница между pluck и select_all:

Если вы pluck данные - ActiveRecord сопоставляет данные с объектами Ruby, такими как Dates, Enums, Модели и т. Д., И это может отличаться от ожидаемого.

Вы можете заметить, что приведенный ниже результат представляет собой строку:

2.5.1 :001 > ActiveRecord::Base.connection.select_all("select created_at from some_ar_class where id = 1 limit 1").rows.first
   (0.6ms)  select created_at from some_ar_classes where id = 1 limit 1
 => ["2018-10-01 01:12:31.758161"]

Пока pluck Даты возврата

2.5.1 :002 > SomeARClass.where(id: 1).pluck(:created_at).first.class
   (0.4ms)  SELECT "some_ar_classes"."created_at" FROM "some_ar_classes" WHERE "some_ar_classes"."id" = $1  [["id", 1]]
 => ActiveSupport::TimeWithZone

То же самое происходит с Enums (int в базе данных, но: символы в Ruby)

И все эти операции разбора / отображения также требуют времени. Это не много, но все же. Поэтому, если вы запрашиваете самый быстрый способ извлечения данных - это, безусловно, необработанный SQL-запрос с connection.select_all, но существуют очень маленькие ситуации, когда вы можете добиться значительного увеличения производительности при этом.

Поэтому я рекомендую использовать pluck.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...