Как записать задачу Граблей импортировать данные к приложению для направляющих?

Цель: Используя задачу КРОНА (или другое запланированное событие) для обновления базы данных с ночным экспортом данных из существующей системы.

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

У меня есть a .txt файл ~5 000 продуктов, который похож на это:

"1234":"product name":"attr 1":"attr 2":"ABC Manufacturing":"2222"
"A134":"another product":"attr 1":"attr 2":"Foobar World":"2447"
...

Все значения являются строками, включенными в двойные кавычки (") это разделяется двоеточиями (:)

Поля:

  • id: уникальный идентификатор; алфавитно-цифровой
  • name: название продукта; любой символ
  • столбцы атрибутов: строки; любой символ (например, размер, вес, цвет, размер)
  • vendor_name: строка; любой символ
  • vendor_id: уникальный идентификатор поставщика; числовой

Информация о поставщике не нормализована в существующей системе.

Что такое лучшие практики здесь? Это должно хорошо удалить продукты и таблицы поставщиков и переписать с новыми данными по каждому циклу? Или лучше только добавить новые строки и обновить существующие?

Примечания:

  1. Эти данные будут использоваться для генерации Orders это сохранится через ночной импорт базы данных. OrderItems должен будет быть подключен к идентификаторам продукта, которые указаны в файле данных, таким образом, мы не можем полагаться на первичный ключ автопостепенного увеличения, чтобы быть тем же для каждого импорта; уникальный алфавитно-цифровой идентификатор должен будет использоваться для присоединения products кому: order_items.
  2. Идеально, я хотел бы, чтобы средство импорта нормализовало данные Поставщика
  3. Я не могу использовать ванильные SQL-операторы, таким образом, я предполагаю, что должен буду записать a rake задача для использования Product.create(...) и Vendor.create(...) синтаксис стиля.
  4. Это будет реализовано на EngineYard
9
задан maček 9 February 2014 в 23:49
поделиться

3 ответа

Я бы не стал удалять таблицы продуктов и поставщиков в каждом цикле. Это приложение для рельсов? В таком случае есть несколько действительно хороших помощников ActiveRecord, которые могут вам пригодиться.

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

p = Product.find_or_initialize_by_identifier(<id you get from file>)
p.name = <name from file>
p.size = <size from file>
etc...
p.save!

find_or_initialize будет искать продукт в базе данных по указанному вами идентификатору, и, если не может найти его, создаст новый.Что действительно удобно в этом способе, это то, что ActiveRecord будет сохранять в базу данных только в том случае, если какие-либо данные изменились, и он будет автоматически обновлять любые поля меток времени, которые у вас есть в таблице (updated_at), соответственно. Еще одна вещь, поскольку вы будете искать записи по идентификатору (id из файла), я обязательно добавлю индекс для этого поля в базе данных.

Чтобы выполнить задачу rake, я бы добавил файл rake в каталог lib / tasks вашего приложения rails. Мы назовем это data.rake.

Внутри data.rake это будет выглядеть примерно так:

namespace :data do
  desc "import data from files to database"
  task :import => :environment do
    file = File.open(<file to import>)
    file.each do |line|
      attrs = line.split(":")
      p = Product.find_or_initialize_by_identifier(attrs[0])
      p.name = attrs[1]
      etc...
      p.save!
    end
  end
end

Чтобы вызвать задачу rake, используйте команду «rake data: import» из командной строки.

14
ответ дан 4 December 2019 в 14:26
поделиться
  • Создайте задачу импортера с копированием
  • Анализируйте файл построчно, используя Faster CSV или с помощью vanilla ruby, например:

file.each do | line | products_array = line.split (":") end

  • Разделите каждую строку на ":" и вставьте в хэш.
  • Используйте find_or_initialize для заполнения вашей базы данных, например:

    Product.find_or_initialize_by_name_and_vendor_id ("foo", 111)

0
ответ дан 4 December 2019 в 14:26
поделиться

Поскольку продукты на самом деле меняются не так часто, лучший способ, который я могу найти, - это обновлять только те записи, которые меняются.

  1. Получить все дельты
  2. Массовое обновление с помощью одного оператора SQL

Если у вас есть код нормализации в моделях, вы можете использовать Product.create и Vendor.create, иначе это будет просто излишним. Кроме того, обратите внимание на вставку нескольких записей в одну транзакцию SQL, это намного быстрее.

0
ответ дан 4 December 2019 в 14:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: