Как использовать update all, когда все записи разные? - PullRequest
13 голосов
/ 07 января 2012

Как я могу использовать update_all, если я хочу обновить столбец из 300 000 записей с различными значениями?

Что я хочу сделать, это что-то вроде:

Model.update_all(:column => [2,33,94,32]).where(:id => [22974,22975,22976,22977]) 

Но, к сожалению, это не работает, и еще хуже для 300 000 записей.

Ответы [ 3 ]

15 голосов
/ 13 августа 2013

Из 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)

Edit: только что взглянул на источник, и это генерирует n SQL-запросов тоже ... Так что, вероятно, не лучшее решение

4 голосов
/ 05 февраля 2016

Единственный способ сделать это - сгенерировать запрос INSERT INTO с обновленными значениями.Для этого я использую gem "activerecord-import" .

Например, у меня есть таблица со значениями val

+--------+--------------+---------+------------+-----+-------------------------+-------------------------+
| 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.url = i}

сохраните записи в одном запросе

CustomProduct.import a.to_a, :on_duplicate_key_update => [:url]

Все ваши записи будут обновлены в одном запросе.Более подробную информацию вы найдете в документации gem "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 голосов
/ 07 января 2012

краткий ответ на ваш вопрос: вы не можете.

Точка update_all состоит в том, чтобы присвоить столбцу одинаковое значение для всех записей (соответствует условию, если оно предусмотрено).Причиной этого является то, что он делает это в одном операторе SQL.

Я согласен с ответом Шайме за правильность.Хотя это сгенерирует n вызовов SQL.Так что, может быть, в твоей проблеме есть что-то еще, о чем ты нам не говоришь.Возможно, вы можете перебирать каждое возможное значение, вызывая update_all для объектов, которые должны обновляться с этим значением.Тогда нужно либо создать соответствующий хеш, либо, что еще лучше, если условие основано на чем-то в самой модели, вы можете передать условие в update_all.

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