Знакомство с графической базой данных Neo4j

Когда-то, году эдак в 2005, я заболел идеей создания базы знаний, которая бы не имела четкой табличной структуры и работала бы на принципе именованных узлов и связей между ними. Основная идея была такая, что сам по себе узел не нес никакой информации, а вся информация бы задавалась его окружением и связями. Я тогда написал небольшой код хранилища этих узлов и связей, а также простейших операций над ними, но совсем не хранить информацию в узлах было слишком сложно и я привязывал к каждому узлу одно текстовое свойство (в Neo4j в узел можно записать много свойств различного типа и потом обращаться к ним по имени).

Этот движок изначально был написан на C#, затем несколько раз переписывался, но постепенно интерес к нему я потерял. Вспомнил ту свою разработку, когда недавно наткнулся на Neo4j, и узнав некоторые свои идеи захотел детальней с ней ознакомиться.

Neo4j я установил на виртуалку, оказалось что встроенный фронт-енд имеет веб-интерфейс и доступен по адресу http://localhost:7474

После перехода по адресу мне было предложено ввести имя пользователя и пароль, при этом давалась подсказка что есть дефолтное имя пользователя “node4j” и пароль такой же. Далее меня ждала страница приветствия, на которой были три основных кнопки — Start Learning, Write Code и Monitor:

Самое первое я перешел на страницу мониторинга и сразу над блоком с кнопками добавился еще один блок, в котором я увидел статистику по БД (на скрине я уже успел добавить одну ноду):

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

В самом верху оказалась командная строка для выполнения местного языка запросов, по аналогии с SQL только тут он называется “Cypher Query Language”. Мне сразу захотелось хоть что нибудь добавить в базу, но не такое сложное, как было предложено во встроенном примере “play movie graph” — там была целая страница команд, которая по видимому создавала целую кучку сущностей со свойствами и связями между ними. Вместо этого я перешел по ссылке на описание команды CREATE и по примеру выполнил CREATE (n), создав просто простейшую отдельную ноду.

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

#org.neo4j.server.webserver.address=0.0.0.0

в файле conf/neo4j-server.properties

Далее попробовал создать несколько нод:

CREATE (a:Country {name:'Украина'}),(b:Country {name:'Россия'}),(c:Country {name:'Беларусь'}),(d:Country {name:'Казахстан'})

я получил:

Added 3 labels, created 4 nodes, set 4 properties, statement executed in 664 ms.

Когда же я захотел связать страны соотношением ‘Border’, то есть указать какая с какой граничат, оказалось что в Neo4j отношение может быть только однонаправленным, но из базы можно делать выборки игнорируя направление. Пришлось смириться с этим и установить связи случайного направления:

MATCH (a:Country {name:'Украина'}),(b:Country {name:'Россия'}),(c:Country {name:'Казахстан'}),(d:Country {name:'Беларусь'}) CREATE (a)-[r:Border]->(b),(a)-[t:Border]->(d),(b)-[y:Border]->(c),(d)-[u:Border]->(b)

Здесь вначале в переменные a,b,c,d выбираются все нужные страны а затем между ними устанавливаются связи с меткой (Label) “Border”. Полюбоваться на получившуюся картину можно выбрав все связи “Border”

MATCH ()-[r:Border]-() RETURN r

либо все старны

MATCH (a:Country) RETURN a

После того как я упражняясь добавил еще несколько стран и связей между ними, уже можно было получить такую картинку:

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

Мне показалось, что встроенный визуализатор должен быть не единственным, и немного поискав я нашел еще несколько примеров визуализаций:

http://neo4j.com/developer/guide-data-visualization/#_presentation_svg_based_graph_interaction

Что интересно, связи тоже могут иметь свойства, как и ноды, но мне показалось не очень понятным ограничение на количество типов связей (по одному источнику 32768 а по другому 65536). В моей БД типы связей задавались самими нодами, что позволяло при надобности строить иерархии типов связей а также иметь гораздо больше их разновидностей.

Оболочка моей БД выглядела примерно так:

Там было общее дерево сущностей, а также отдельные формы для работы с некоторыми типами сущностей, как то персоналии (по сути телефонный справочник), каталог дисков. Все что угодно можно было посмотреть в виде списка либо дерева. Предполагалось что я в результате выработаю некую удобную форму хранения знаний, которые легко между собой переплетаются и не имеют четкой однородной структуры. Сейчас конечно я не думаю что обязательно было разрабатывать БД с нуля, а вполне можно было за основу взять Firebird, MySQL и реализовать механизм хранения/выборки нод и связей между ними в виде таблиц. Сейчас в одном из своих экспериментов я собственно так и делаю.