Как использовать все обновления, когда все записи отличаются?
Как я могу использовать update_all
, если я хочу обновить столбец из 300 000 записей со всеми различными значениями?
Я хочу сделать что-то вроде:
Model.update_all(:column => [2,33,94,32]).where(:id => [22974,22975,22976,22977])
Но, к сожалению, это не работает, и это еще хуже для 300 000 записей.
Ответы
Ответ 1
В документации ActiveRecord # обновления:
people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
Person.update(people.keys, people.values)
Итак, в вашем случае:
updates = {22974 => {column: 2}, 22975 => {column: 33}, 22976 => {column: 94}, 22977 => {column: 32}}
Model.update(updates.keys, updates.values)
Изменить: просто посмотрел на источник, и это также генерирует n SQL-запросов... Возможно, это не лучшее решение
Ответ 2
Единственный способ сделать это - сгенерировать запрос INSERT INTO с обновленными значениями. Для этого я использую гем "activerecord-import".
Например,
У меня есть таблица со значениями val values
+--------+--------------+---------+------------+-----+-------------------------+-------------------------+
| pkey | id | site_id | feature_id | val | created_at | updated_at |
+--------+--------------+---------+------------+-----+-------------------------+-------------------------+
| 1 | | 125 | 7 | 88 | 2016-01-27 10:25:45 UTC | 2016-02-05 11:18:14 UTC |
| 111765 | 0001-0000024 | 125 | 7 | 86 | 2016-01-27 11:33:22 UTC | 2016-02-05 11:18:14 UTC |
| 111766 | 0001-0000062 | 125 | 7 | 15 | 2016-01-27 11:33:22 UTC | 2016-02-05 11:18:14 UTC |
| 111767 | 0001-0000079 | 125 | 7 | 19 | 2016-01-27 11:33:22 UTC | 2016-02-05 11:18:14 UTC |
| 111768 | 0001-0000086 | 125 | 7 | 33 | 2016-01-27 11:33:22 UTC | 2016-02-05 11:18:14 UTC |
+--------+--------------+---------+------------+-----+-------------------------+-------------------------+
выберите записи
products = CustomProduct.limit(5)
обновлять записи по мере необходимости
products.each_with_index{|p, i| p.val = i}
сохранять записи в одном запросе
CustomProduct.import products.to_a, :on_duplicate_key_update => [:val]
Все ваши записи будут обновлены в одном запросе. Для получения более подробной информации, пожалуйста, обратитесь к гему "activerecord-import".
+--------+--------------+---------+------------+-----+-------------------------+-------------------------+
| pkey | id | site_id | feature_id | val | created_at | updated_at |
+--------+--------------+---------+------------+-----+-------------------------+-------------------------+
| 1 | | 125 | 7 | 0 | 2016-01-27 10:25:45 UTC | 2016-02-05 11:19:49 UTC |
| 111765 | 0001-0000024 | 125 | 7 | 1 | 2016-01-27 11:33:22 UTC | 2016-02-05 11:19:49 UTC |
| 111766 | 0001-0000062 | 125 | 7 | 2 | 2016-01-27 11:33:22 UTC | 2016-02-05 11:19:49 UTC |
| 111767 | 0001-0000079 | 125 | 7 | 3 | 2016-01-27 11:33:22 UTC | 2016-02-05 11:19:49 UTC |
| 111768 | 0001-0000086 | 125 | 7 | 4 | 2016-01-27 11:33:22 UTC | 2016-02-05 11:19:49 UTC |
+--------+--------------+---------+------------+-----+-------------------------+-------------------------+
Ответ 3
короткий ответ на ваш вопрос, вы не можете.
Точка update_all должна назначить значение того же для столбца для записей all (соответствующих условию при условии). Причиной является то, что он делает это в одном выражении SQL.
Я согласен с ответом Shime на правильность. Хотя это вызовет n SQL-запросов. Итак, возможно, в вашей проблеме есть что-то еще, о чем вы нам не говорите. Возможно, вы можете перебирать все возможные значения, вызывая update_all для объектов, которые должны обновляться с этим значением. Тогда это вопрос построения соответствующего хэша или, что еще лучше, если условие основано на чем-то в самой модели, вы можете передать условие update_all.