Подтвердить что ты не робот

Пакетная вставка в рельсы 3

Я хочу сделать пакетную вставку из нескольких тысяч записей в базу данных (POSTGRES в моем случае) из моего приложения Rails.

Каким будет "Rails" для этого? Что-то быстрое, а также правильный способ сделать это.

Я знаю, что могу создать sql-запрос путем конкатенации строк, но мне нужен лучший подход.

4b9b3361

Ответ 1

ActiveRecord .create метод поддерживает массовое создание. Метод эмулирует эту функцию, если БД ее не поддерживает и использует базовый механизм БД, если эта функция поддерживается.

Просто передайте массив параметров.

# Create an Array of new objects
User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])

Поддерживается блок, и это общий способ для общих атрибутов.

# Creating an Array of new objects using a block, where the block is executed for each object:
User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u|
  u.is_admin = false
end

Ответ 2

Наконец, я получил решение после двух ответов @Симоне Карлетти и @Sumit Munot.

Пока драйвер postgres не поддерживает массовую вставку метода ActiveRecord.create, я хотел бы пойти с activerecord-import gem. Он делает объемную вставку, и это тоже в одном заявлении вставки.

books = []
10.times do |i| 
    books << Book.new(:name => "book #{i}")
end
Book.import books

В POSTGRES это приводит к созданию одной статистики stat.

Как только драйвер postgres поддерживает массовую вставку метода ActiveRecord.create в одном заявлении insert, тогда решение @Simone Carletti имеет больше смысла:)

Ответ 3

Вы можете создать script в своей модели рельсов, написать свои запросы, чтобы вставить в это script В рельсах вы можете запустить script с помощью

rails runner MyModelName.my_method_name

Это лучший способ, который я использовал в своем проекте.

Update:

Я использую следующее в своем проекте, но он не подходит для SQL-инъекции. если вы не используете пользовательский ввод в этом запросе, он может сработать для вас

user_string = " ('[email protected]','a'), ('[email protected]','b')"
User.connection.insert("INSERT INTO users (email, name) VALUES"+user_string)

Для нескольких записей:

new_records = [
  {:column => 'value', :column2 => 'value'}, 
  {:column => 'value', :column2 => 'value'}
]

MyModel.create(new_records)

Ответ 4

Вы можете сделать это быстрым способом или способом Rails;) Самый лучший способ в моем опыте импортировать массивные данные в Postgres - через CSV. Что займет несколько минут, путь Rails займет несколько секунд, используя встроенную возможность импорта CSV Postgres.

http://www.postgresql.org/docs/9.2/static/sql-copy.html

Он даже запускает триггеры базы данных и уважает ограничения базы данных.

Изменить (после вашего комментария): Попался. В этом случае вы правильно описали свои два варианта. Раньше я был в той же ситуации, реализовал его, используя Rails 1000 save! потому что это была самая простая вещь, которая работала, а затем оптимизировала ее для стратегии "добавить огромную строку запроса", поскольку она была на порядок лучше.

Конечно, преждевременная оптимизация - это корень всего зла, поэтому, возможно, сделать это простым медленным способом Rails и знать, что построение большой строки запроса является совершенно законным методом оптимизации за счет поддержания работоспособности. Я чувствую, что ваш реальный вопрос: "Есть ли способ Railsy, ​​который не включает 1000 запросов?" - К сожалению, ответ на этот вопрос - нет.