Импорт большого набора данных в базу данных - PullRequest
1 голос
/ 15 марта 2010

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

Я пытаюсь импортировать набор данных OpenLibrary в локальную базу данных Postgres. После того, как он будет импортирован, я планирую использовать его в качестве начального начального числа для приложения Ruby on Rails, которое будет содержать информацию о книгах.

Наборы данных OpenLibrary доступны здесь в измененном формате JSON: http://openlibrary.org/dev/docs/jsondump

Мне нужна только очень базовая информация для моего приложения, намного меньше, чем то, что указано в дампах. Я только пытаюсь узнать названия книг, имена авторов и отношения между книгами и авторами.

Ниже приведены две типичные записи из их набора данных: первая для автора и вторая для книги (кажется, что они имеют запись для каждого издания книги). Кажется, что записи начинаются с первичного ключа, а затем с типом, прежде чем включать фактический дамп базы данных JSON.

/ a / OL2A / type / author {"name": "U. Venkatakrishna Rao", "personal_name": "U. Venkatakrishna Rao", "last_modified": {"type": "/ type / datetime", "значение": "2008-09-10 08: 44: 01.978456"}, "ключ": "/ a / OL2A", "дата рождения": "1904", "тип": {"ключ": "/ тип / author "}," id ": 99," revision ": 3}

/ b / OL345M / type / edition {"publishers": ["Проект исследований в области социальных наук, кафедра географии, Университет Дакки"], "pagination": "ii, 54 p.", "Title": «Землепользование в районе Фаядабада», «lccn»: [«sa 65000491»], «subject_place»: [«Восточный Пакистан», «Регион Дакка»], «number_of_pages»: 54, «languages»: [{"comment ":" initial import "," code ":" eng "," name ":" English "," key ":" / l / eng "}]," lc_classification ": [" S471.P162 E23 "]," publish_date ":" 1963 "," publish_country ":" pk "," key ":" / b / OL345M "," авторы ": [{" birth_date ":" 1911 "," name ":" Nafis Ahmad "," key ":" / a / OL302A "," personal_name ":" Nafis Ahmad "}]," publish_places ": [" Dacca, East Pakistan "]," by_statement ":" [by] Нафис Ахмад и Ф. Карим Хан. "," oclc_numbers ": [" 4671066 "]," members ": [" Хан, Фазле Карим, соавтор. "]," subject ": [" Землепользование - Восточный Пакистан - регион Дакка. "]}

Размер несжатых дампов огромен: около 2 ГБ для списка авторов и 18 ГБ для списка изданий книг. OpenLibrary не предоставляет никаких инструментов для этого, они предоставляют простой неоптимизированный скрипт Python для чтения примеров данных (который, в отличие от реальных дампов, представлен в чистом формате JSON), но они оценивают, если он был изменен для использования на их реальных данных, он будет займет 2 месяца (!), чтобы закончить загрузку данных.

Как я могу прочитать это в базу данных? Я предполагаю, что мне нужно написать программу для этого. На каком языке и каких-либо указаниях о том, как мне это сделать, чтобы закончить в разумные сроки? Единственный язык сценариев, с которым у меня есть опыт, это Ruby.

Ответы [ 3 ]

1 голос
/ 16 марта 2010

Для загрузки дампа с их сайта потребуется два месяца. Но это займет всего несколько часов, чтобы импортировать это.

Самый быстрый способ для вас - использовать команду копирования Postgres. Вы можете использовать это для файла автора. Но файл редакций нужно вставить в таблицы books и author_books.

Этот скрипт написан на Python 2.6, но при необходимости вы сможете адаптироваться к Ruby.

!#/usr/bin/env python
import json

fp = open('editions.json')
ab_out = open('/tmp/author_book.dump', 'w')
b_out = open('/tmp/book.dump', 'w')
for line in fp:
  vals = json.loads(s.split('/type/edition ')[1])
  b_out.write("%(key)s\t%(title)s\t(publish_date)s" % vals)
  for author in vals['authors']:
    ab_out.write("%s\t%s" % (vals['key'], author['key'])
fp.close()
ab_out.close()
b_out.close()

Затем скопировать в Postgres:

COPY book_table FROM '/tmp/book.dump'
0 голосов
/ 17 марта 2010

Следуя совету Скотта Бэйли, я написал сценарии Ruby для изменения JSON в формат, приемлемый для команды копирования Postgres. Если кто-то столкнется с этой же проблемой, вот сценарии, которые я написал:

require 'rubygems'
require 'json'

fp = File.open('./edition.txt', 'r')
ab_out = File.new('./author_book.dump', 'w')
b_out = File.new('./book.dump', 'w')

i = 0
while (line = fp.gets) 
  i += 1
  start = line.index /\{/
  if start
    to_parse = line[start, line.length]
    vals = JSON.parse to_parse

    if vals["key"].nil? || vals["title"].nil?
      next
    end
    title = vals["title"]
    #Some titles contain backslashes and tabs, which we need to escape and remove, respectively
    title.gsub! /\\/, "\\\\\\\\"
    title.gsub! /\t/, " "
    if ((vals["isbn_10"].nil? || vals["isbn_10"].empty?) && (vals["isbn_13"].nil? || vals["isbn_13"].empty?))
      b_out.puts vals["key"] + "\t" + title + "\t" + '\N' + "\n"
    #Only get the first ISBN number
    elsif (!vals["isbn_10"].nil? && !vals["isbn_10"].empty?) 
      b_out.puts vals["key"] + "\t" + title + "\t" + vals["isbn_10"][0] + "\n"
    elsif (!vals["isbn_13"].nil? && !vals["isbn_13"].empty?)
      b_out.puts vals["key"] + "\t" + title + "\t" + vals["isbn_13"][0] + "\n"    
    end
    if vals["authors"]
      for author in vals["authors"]
        if !author["key"].nil?
          ab_out.puts vals["key"] + "\t" + author["key"]
        end
      end
    end
  else
    puts "Error processing line: " + line.to_s
  end
  if i % 100000 == 0
    puts "Processed line " + i.to_s
  end
end

fp.close
ab_out.close
b_out.close

и

require 'rubygems'
require 'json'

fp = File.open('./author.txt', 'r')
a_out = File.new('./author.dump', 'w')

i = 0
while (line = fp.gets) 
  i += 1
  start = line.index /\{/
  if start
    to_parse = line[start, line.length]
    vals = JSON.parse to_parse

    if vals["key"].nil? || vals["name"].nil?
      next
    end
    name = vals["name"]
    name.gsub! /\\/, "\\\\\\\\"
    name.gsub! /\t/, " "
    a_out.puts vals["key"] + "\t" + name + "\n"
  else
    puts "Error processing line: " + line.to_s
  end
  if i % 100000 == 0
    puts "Processed line " + i.to_s
  end
end

fp.close
a_out.close
0 голосов
/ 15 марта 2010

Не знаю, если TAPS поможет вам здесь

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