Как использовать все обновления, когда все записи отличаются?

Как я могу использовать 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.