Статьи

Импорт MusicBrainz (музыкальная база данных с открытым контентом) в Neo4j

Эта статья была первоначально написана Полом Трембертом

Что такое MusicBrainz?


Цитируя
Википедию ,
MusicBrainz — это «музыкальная база данных с открытым контентом, [которая] была основана в ответ на ограничения, наложенные на CDDB. (…) MusicBrainz собирает информацию об артистах, их записанных работах и ​​отношениях между ними».

http://en.wikipedia.org/wiki/MusicBrainz

Любой может просмотреть базу данных по адресу
http://musicbrainz.org/ . Если вы создадите с ними учетную запись, вы сможете добавить новые данные или исправить данные существующих записей, отследить длительность, отправить в отсканированные изображения ваших любимых альбомов и т. Д. Изменения рецензируются, и любой участник может проголосовать за или против. Есть много общего с Википедией.

В этом первом посте мы хотим показать вам, как импортировать данные Musicbrainz в Neo4j для дальнейшего анализа с
Cypher во втором посте. Смотрите ниже, что мы получим в итоге:
Американские артисты подписались на британские лейблы

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

START usa=node:mb_fulltext(name="United States"),
gb=node:mb_fulltext(name="United Kingdom")
MATCH (usa:Country), (gb:Country),
(a:Artist)-[:FROM_AREA]-(usa),
(a:Artist)-[:RECORDING_CONTRACT]-(l:Label),
(l)-[:FROM_AREA]-(gb)
RETURN a,l,usa,gb

MusicBrainz Data


MusicBrainz в настоящее время насчитывает 
около 1000 активных пользователей , около 800 000 исполнителей, 75 000 звукозаписывающих лейблов, около 1 200 000 релизов, более 12 000 000 треков и короткие URL-адреса менее 2 000 000 для этих объектов (страниц Википедии, официальных домашних страниц, каналов YouTube и т. Д.) Ежедневные исправления сообщества делает их данные, вероятно, самыми свежими и точными в Интернете.

Вы можете проверить текущие номера
здесь  и
здесь .

Это много взаимосвязанных данных! Что делает его идеальным кандидатом на Neo4j.

Все объекты (исполнители, лейблы, релизы и т. Д.) Идентифицируются по их
идентификатору MusicBrainz (MBID. Вероятно, он наиболее близок к универсальному UUID для индустрии звукозаписи. Чтобы найти MBID своей любимой группы, выполните поиск на главной странице сайта). В строке поиска вверху щелкните по нужному исполнителю (может быть много омонимов), а в адресной строке вашего браузера MBID является последней частью URL-адреса. Например, это URL-адрес страницы Maxïmo Park на MusicBrainz:


Их MBID — «
92e634a7-6023-4be8-be15-ebba822f5b34 ».
MBID стал де-факто точкой отсчета для музыкальных данных, с , например , Last.fm и многие другие , используя его

Лицензия данных Musicbrainz


Когда речь идет об общедоступных источниках данных, вопрос об их лицензии всегда является одним из первых вопросов, на которые следует обратить внимание.
В случае с Musicbrainz это две интерпретации.

Основные данные

Основные данные, как отмечалось выше, лицензируются в рамках
CC0 , который фактически помещает данные в общественное достояние. Это означает, что каждый может загружать и использовать основные данные любым удобным для них способом. Никаких ограничений, никаких забот!

Из Википедии,

Начиная с 2003 года
[10] Основные данные MusicBrainz ( в художники, записи, альбомы и т.д.) находятся в
общественном достоянии , и дополнительного контента, включая данные модерации ( по сути каждый
оригинальный контент , пополняемая пользователями и его проработок), находится под
Лицензия
Creative Commons
CC-BY-NC-SA -2.0.

Реляционная модель


Сервер MusicBrainz написан на Perl с бэкэндом PostgreSQL.
Это на самом деле с открытым исходным кодом. и вы можете взглянуть на схему таблицы на github:
https://github.com/metabrainz/musicbrainz-server/blob/master/admin/sql/CreateTables.sql

Вот как разные таблицы связаны в реляционной модели MusicBrainz:


Как вы можете видеть, таблицы глубоко нормализованы, и это немного пугает, когда вы начинаете в них погружаться.
(так называемая NGS, схема следующего поколения,
http://wiki.musicbrainz.org/Next_Generation_Schema )

Как бы выглядели данные MusicBrainz на графике?


Сущностям на нашем графике будут назначены метки Neo4j, которые приблизительно соответствуют именам таблиц SQL (именам в пузырьках).
Ниже приведено упрощенное представление о том, как сущности MusicBrainz связаны в графовой модели Neo4j:
Neo4j Musicbrainz Схема

Что с компанией «Artist Credit»?


Ну, это когда несколько исполнителей работали или играли на треке или записи.

Например, «Телефон» Леди Гага также включает в себя Бейонсе (
http://musicbrainz.org/recording/4daf26b7-7cf3-4752-bebc-9bb23a4648e1 ), так что в этой записи упоминается два художника, Леди Гага (MBID 650e7db6- b795-4eb5-a702-5ea2fc46c848) и Бейонсе (MBID 859d0860-d480-4efd-970c-c05d5f1776b8). Но заслуга трека — «Lady Gaga feat. Бейонсе». Вы можете найти более подробную информацию здесь:
http://musicbrainz.org/doc/Artist_Credit

Как импортировать данные MusicBrainz в Neo4j?


«Это все красиво и красиво, но как мне получить этот замечательный набор данных в Neo4j?»

Инструмент SQL2GRAPH

sql2graph был вдохновлен постами Макса Де Марци в блоге об использовании пакетного импорта: часть 1 (http://maxdemarzi.com/2012/02/28/batch-importer-part-1/) и часть 2 (http: // maxdemarzi) .com / 2012/02/28 / партии-импортер-часть-2 /). Это набор скриптов Python, которые упрощаются при переходе с реляционных баз данных на Neo4j, примером чего является миграция Musicbrainz,
подробные инструкции
см. Здесь .

Шаг 1 — получить локальную копию базы данных


Вы можете иметь свое собственное зеркало PostgreSQL базы данных MusicBrainz, используя изящный проект Python под названием «mbslave» Лукаша Лалинского (
https://bitbucket.org/lalinsky/mbslave ) и передать его дампом
базы данных MusicBrainz (получите этот дамп после инструкции от
http://wiki.musicbrainz.org/MusicBrainz_Database/Download ). Основной дамп данных
mbdump.tar.bz2 находится в открытом доступе и составляет 1,5 ГБ. Пожалуйста, используйте зеркало, которое наиболее близко к вам (ЕС или США). Вы должны быть хороши, чтобы пойти с этим.

См.
Http://musicbrainz.org/doc/MusicBrainz_Database/Download для других способов получения данных (виртуальная машина, зеркало MySQL).

Шаг 2 — Экспорт данных в CSV / TSV с помощью sql2graph


Для такого объема данных (около 30 миллионов основных объектов и множества взаимосвязей между ними) мы рекомендуем инструмент, который мы предлагаем:
проект пакетного импорта Майкла Хангера
 (сейчас выберите ветку «20» для поддержки Neo4j 2.0)
.

Это инструмент, который принимает TAB-файлы значений в качестве входных данных и заполняет хранилище данных Neo4j.
Формат довольно прост и обычно требует всего два файла: первый с узлами и их свойствами, а второй — для связи между этими узлами.

Вы можете создать эти файлы несколькими способами, но я написал модуль Python, чтобы помочь вам с этим: sql2graph (
https://github.com/redapple/sql2graph )

Как работает sql2graph


sql2graph также нуждается в небольшой помощи от вас, поскольку он принимает в качестве входных данных (Python) представление схемы, сопоставляющей таблицы SQL с узлами, свойствами и связями графа.
(Классы Python, используемые в отображении схемы sql2graph, заимствованы из кода mbslave для экспорта MusicBrainz в Solr.)

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

Например, таблица «Artist» (
https://github.com/metabrainz/musicbrainz-server/blob/master/admin/sql/CreateTables.sql#L95 ) сопоставлена ​​с:
Entity('artist',
 [
   IntegerProperty('pk', Column('id')),
   Property('mbid', Column('gid')),
   Property('disambiguation', Column('comment')),
   Property('name', Column('name')),
 ],

Все экземпляры Entity () имеют:

  • имя, здесь «исполнитель», которое станет меткой: Artist для узлов.

  • список экземпляров Property (), которые также имеют имя, которое станет свойствами узла

  • обязательное свойство первичного ключа, называемое «pk», которое используется sql2graph для разрешения связей между сущностями при создании отношений;
    обычно это имя столбца «id» в таблицах SQL (это свойство «pk» не очень полезно в конечном графике)

Каждое свойство () может ссылаться на столбец SQL в той же таблице или в связанной таблице (через экземпляр ForeignColumn () в качестве второго параметра)

А как насчет отношений?


Субъекты могут иметь отношения с другими сущностями (вот и весь смысл в том, чтобы поместить их в график, верно?).
Вы определяете их после списка свойств для своих узлов, как список экземпляров Relation ().

Давайте продолжим с примером сущности «Artist»,

Entity('artist',
 [
   IntegerProperty('pk', Column('id')),
   Property('mbid', Column('gid')),
   Property('disambiguation', Column('comment')),
   Property('name', Column('name', ForeignColumn('artist_name', 'name'))),
 ],
 [
   Relation(
     'FROM_AREA',
     start=Reference('artist', Column('id')),
     end=Reference('area', Column('area')),
     properties=[]
   ),
   Relation(
     'BEGAN_IN_AREA',
     start=Reference('artist', Column('id')),
     end=Reference('area', Column('begin_area')),
     properties=[]
   ),
   Relation(
     'ENDED_IN_AREA',
     start=Reference('artist', Column('id')),
     end=Reference('area', Column('end_area')),
     properties=[]
   ),
 ],
),

Мы только что определили 3 типа отношений:

  • «ОТ»: представляет связь между таблицей «художник» и таблицей «площадь», представляющую, откуда художник (родился или построил свою карьеру)

  • «BEGAN_IN» и «ENDED_IN» также представляют собой связь между таблицами «Artist» и «Area», но они представляют место рождения и место смерти исполнителя (или группы иногда)

Все отношения должны иметь «начальную сущность» и «конечную сущность», используя класс Reference (), который очень похож на класс Property ().

Наконец, отношения также могут иметь свои собственные свойства.
Таким образом, вы можете добавить объекты Property () в качестве четвертого параметра в Relation. Пример с таблицей release_label, которая связывает выпуск с лейблом звукозаписи, который выпустил его (очевидно;), и эта таблица может содержать информацию о номере по каталогу. Это переводится на:

Entity('release_label',
  [],
  [
    Relation(
     'RELEASED_ON',
     start=Reference('release', Column('release')),
     end=Reference('label', Column('label')),
     properties=[
       Property('catalog_number', Column('catalog_number')),
     ]
   ),
 ]
),

Для таблицы «release_label» нам не нужно создавать узлы в Neo4j, нас интересует только связь между двумя сущностями «release» и «label», поэтому параметры Properties оставлены в пустом списке Python, [ ].

Экспорт узлов и отношений с использованием запросов SQL


Как только вы определили это отображение схемы, вы можете запустить sql2graph, и он выведет хороший SQL-скрипт, который вы дадите psql, который можно экспортировать напрямую в TSV.

sql2graph был вдохновлен постами Макса Де Марци в блоге об использовании пакетного импорта: часть 1 (
http://maxdemarzi.com/2012/02/28/batch-importer-part-1/ ) и часть 2 (
http: // maxdemarzi) .com / 2012/02/28 / партия-импортер-часть-2 / )

Работает в 3 этапа:

  • во-первых, он создает временную таблицу (в самой СУБД), сопоставляющую значения первичных ключей объекта с идентификаторами узлов в Neo4j.
    Эта таблица SQL имеет 3 столбца: «entity», «pk» и «node_id»

  • затем он сбрасывает данные узлов для всех таблиц, для которых вы определили свойства узлов в формате TSV (PostgreSQL может сделать это, см.
    http://maxdemarzi.com/2012/02/28/batch-importer-part-2/ )

  • наконец, он экспортирует отношения как TSV, используя экземпляры Relation () и Property (), которые вы определили в приведенном выше сопоставлении, и обрабатывает идентификаторы узлов с использованием временной таблицы.

SQL таблица «художник»:

мне бы

гид (мбид)

название

тип

1

859d0860-d480-4efd-970C-c05d5f1776b8

Бейонсе

Человек

2

f27ec8db-af05-4f36-916e-3d57f91ecf5e

Майкл Джексон

Человек

Таблица SQL «метка»:

мне бы

гид (мбид)

название

тип

1

46f0f4cd-8aab-4b33-b698-f459faf64190

Отчеты Деформации

2

42e06800-76f8-4a5b-a9b6-0983a5d72f17

Jagjaguwar

Оригинальная продукция

Временный картографический стол:

юридическое лицо

рк

node_id

художник

1

1

художник

2

2

метка

1

3

метка

2

4

«О, чувак, но у MusicBrainz так много таблиц … Нужно ли мне самому определять эту вещь для перевода схемы? а в питоне ?? На самом деле мы сделали всю работу за вас. Либо настройте отображение, чтобы добавить или удалить несколько свойств или сущностей, и запустите sql2graph… или просто захватите сценарий экспорта SQL и отправьте его в psql.


$ git clone [email protected]: redapple / sql2graph.git

$ cd sql2graph

$ ./musicbrainz2neo4j-export.py> musicbrainz2neo4j.sql

Предварительно сгенерированный файл SQL доступен по адресу sql2graph / examples / musicbrainz / musicbrainz2neo4j.sql

batch-import поддерживает автоматическую индексацию, если столбцы вашего CSV-заголовка содержат тип и имя индекса, например «name: string: mb», если поле «name» в узлах является строкой, которую вы хотите проиндексировать в индексе с именем «mb» ,

$ cd / path / to / mbslave

$ cat /path/to/musicbrainz2neo4j.sql |
./mbslave-psql.py

Сгенерированный выше скрипт экспорта MusicBrainz SQL предполагает 2 индекса: «mb_fulltext» в качестве полнотекстового индекса и «mb_exact» в качестве точного индекса. Убедитесь, что ваш файл batch.properties объявляет эти 2 индекса (см. Ниже «Импорт с использованием batch-import»):
  •  Столбцы «mbid» будут проиндексированы в индексе «mb_exact»,  а столбцы «type» станут метками на узлах.

  • «Имя» будет проиндексировано в индексе «mb_fulltext»

По умолчанию сценарий экспорта SQL сообщает psql выводить два файла в каталог / tmp, один для узлов и один для отношений: musicbrainz__full__nodes.csv и musicbrainz__full__rels.csv.

Шаг 3 — Импорт с использованием пакетного импорта Neo4j


Запуск пакетного импорта с этими двумя файлами должен дать вам что-то вроде: (на маленьком компьютере Пола это занимает примерно 1 час и 30 минут, на лучшем MacBookPro около 20 минут).
Обязательно настройте конфигурацию neo4j так, чтобы у импортера были хорошие ресурсы. Файл Peters 
batch.properties выглядит примерно так
batch_import.keep_db=true
batch_import.mapdb_cache.disable=true
batch_import.node_index.mb_fulltext=fulltext
batch_import.node_index.mb_exact=exact
batch_import.csv.quotes=false
cache_type=none
use_memory_mapped_buffers=true
neostore.nodestore.db.mapped_memory=300M
neostore.relationshipstore.db.mapped_memory=3G
neostore.propertystore.db.mapped_memory=500M
neostore.propertystore.db.strings.mapped_memory=500M
neostore.propertystore.db.arrays.mapped_memory=0M
neostore.propertystore.db.index.keys.mapped_memory=15M
neostore.propertystore.db.index.mapped_memory=15M

При этом мы можем импортировать файлы (используя кодировку UTF-8) с помощью:

cd / path / to / jexp / batch-import
MAVEN_OPTS = «- server -Xmx10G -Dfile.encoding = UTF-8» mvn exec: java -Dfile .encoding = UTF-8 -Dexec.mainClass = «org.neo4j.batchimport.Importer» -Dexec.args = «batch.properties musicbrainz.db /tmp/musicbrainz__nodes__full.csv /tmp/musicbrainz__rels__full.csv: get: ccs»

:


Использование java -jar batchimport.jar data / dir node.csv relationss.csv [node_index имя-индекса-узла полный текст | точные узлы-индексы.csv rel_index-имя-индекса полное имя-текста | точное значение rels_index.csv ….]

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

Импорт musicbrainz__nodes__full.csv …

………………………………………….. ………………………………………….. 512172 мс для 10000000

………………………………………….. ………………………………………….. 608539 мс для 10000000

………………………………………….. ………………………………………….. 588464 мс для 10000000

………………………………………….. ..

Импорт 35294004 узлов занял 2057 секунд

Импорт musicbrainz__rels__full.csv …

………………………………………….. ………………………………………….. 438932 мс для 10000000

………………………………………….. ………………………………………….. 338665 мс для 10000000

………………………………………….. ………………………………………….. 194668 мс на 10000000

………………………………………….. ………………………………………….. 421573 мс для 10000000

………………………………………….. ………………………………………….. 535700 мс для 10000000

………………………………………….. ………………………………………….. 529039 мс для 10000000

………………………………………….. ………………………………………….. 634684 мс на 10000000

…………………..

Импорт 72373185 отношений занял 3249 секунд

Общее время импорта: 5595 секунд

Пол @ хриплый: / путь / к / Neo4j / MusicBrainz $

Теперь давайте нацелим наш сервер Neo4j на нашу недавно созданную базу данных Musicbrainz в ее
neo4j-server.properties и рассмотрим пример запроса: Вуаля!
Британские артисты подписались на американских звукозаписывающих лейблах

Запрос Cypher для этого результата:
START usa=node:mb_fulltext(name="United States"),
gb=node:mb_fulltext(name="United Kingdom")
MATCH (gb:Country), (gb:Country),
(a:Artist)-[:FROM_AREA]-(gb),
(a:Artist)-[:RECORDING_CONTRACT]-(l:Label),
(l)-[:FROM_AREA]-(usa)
RETURN a,l,usa,gb

В следующем посте мы рассмотрим несколько интересных запросов по этим данным, следите за обновлениями!

Большое спасибо Michael Hunger, Peter Neubauer, Max DeMarzi и фантастическому сообществу Neo4j за помощь и вдохновение для этого блога!