使用 RAKE 任务将 CSV 移动到 POSTGRES 关系数据库

Use RAKE Task to move CSV to POSTGRES relational DB

我有以下型号。

class Lesson < ActiveRecord::Base
  has_many :books
  has_many :vocabularies
  has_many :sentenses
end

class Book < ActiveRecord::Base
  belongs_to :lesson
end

class Vocabulary < ActiveRecord::Base
  belongs_to :lesson
end

class Sentense < ActiveRecord::Base
  belongs_to :lesson
end

具有以下 table 架构:

Table Lesson [lesson_number, lesson_name]
Table Books [lesson_id, page_start, page_finish]
Table Vocabulary [lesson_id, word, meaning]
Table Sentences [lesson_id, sentence, sentence meaning]

我有一个包含 15,000 节课的 CSV 文件。 CSV 文件在所有课程计划中始终使用 2 本书、10 个词汇、2 个句子的相同结构。

我的想法是这样开始的。

namespace :import_csv do
  desc "IMPORT Lessons"
  task :lessons => :environment do
    CSV.foreach('CcyTbl.csv') do |row|
      lesson_name_id = row[0]
      lesson_name = row[1]
      Lesson.create(lesson_name_id: lesson_name_id, lesson_name: lesson_name)
    end
  end

  desc "IMPORT BOOKS"
  task :books => :environment do
    CSV.foreach('CcyTbl.csv') do |row|
      lesson_name_id = row[0]
      book_name = row[3]
      book_start_pg = row[7]
      book_end_pg = row[8]
      Lesson.create(lesson_name_id: lesson_name_id, book_name: book_name, book_end_pg: book_end_pg)
  end
end

这似乎很简单,但我正在努力:

  1. 如何处理空值。
  2. 有些课有两本书 (认为第 3 列有 book1,book2 是第 9 列,有时 book2 为空)
  3. 课程可能包含 5-10 个词汇 (第10栏词汇1,第11栏词汇1含义,第12栏词汇等)

将此 CSV 中的数据导入各自的 table 的最佳方法是什么?创建多个 rake 任务来完成每个部分是否更有意义,还是可以一次性完成?

更新 这是 link 到 header 行和第一行数据的示例。 (分享图片有点长。)

您可能想要创建一个数据对象,以便更轻松地处理 CSV 数据。将 CSV 格式与模型创建解耦将使整个过程更简单:

csv = CSV.new(body, headers: true, header_converters: :symbol, converters: :all)
data = csv.to_a.map {|row| row.to_hash }

参见 CSV reference

现在我们可以轻松访问每个字段。

data.each do |d|  
  lesson = Lesson.create!(d[:join], ...)
  book = Book.create!(lesson: lesson, page_start:..)
end

顺便说一句,FWIW,

class Sentense < ActiveRecord::Base

应该是

class Sentence < ActiveRecord::Base