2014-10-08 1 views
3

Я только начинаю с Neo4j и Graph Databases и задавался вопросом, являются ли вложенные иерархические деревья хорошим примером для Neo4j. Общим примером может служить вложенный набор комментариев. Например:Как реализовать вложенное дерево в Neo4j?

- Article 
    - Comment 1 on Article 
    - Comment 2 on Comment 1 
    - Comment 3 on Comment 1 
     - Comment 4 on Comment 3 
    - Comment 5 on Article 

Как я понимаю, статья и комментарии были бы узлами. И каждый комментарий будет иметь отношения родитель-ребенок. Получить все прямые комментарии к статье (1 и 5) было бы легко. Но как насчет получения всего набора?

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

ответ

5

Ну, потому что trees actually are graphs, используя базу данных графа для хранения дерева, кажется мне абсолютно подходящим. То, что будет работать лучше всего, будет зависеть от ваших шаблонов доступа к данным, но в основном деревья - это просто специализация графиков.

Да, в вашем случае «элементами в дереве» будут узлы, а «гнездование» будет отношениями. Так вот, как вы могли бы дразнить ваш пример:

CREATE (root:Article {label: "Article"}), 
     (c1:Comment {label: "Comment 1"}), 
     (c1a:Comment {label: "Comment 2 on comment 1"}), 
     (c1b:Comment {label: "Comment 3 on comment 1"}), 
     (c1b1:Comment {label: "Comment 4 on comment 3"}), 
     (c2:Comment {label: "Comment 5 on article"}), 
     (root)<-[:reply]-(c1), 
     (c1)<-[:reply]-(c1a), 
     (c1)<-[:reply]-(c1b), 
     (c1b)<-[:reply]-(c1b1), 
     (root)<-[:reply]-(c2); 

Это просто создает кучу узлов и связей, имитируя структуру вы предоставили. Здесь я всегда использовал :reply для подключения.

Теперь «получает все» просто означает, что обход всех :reply отношений, которые мы создали:

MATCH p=(a:Article {label: "Article"})<-[:reply*1..]-(otherThing) 
WITH nodes(p) as nodes 
RETURN nodes[length(nodes)-2] as InResponseTo, 
     nodes[length(nodes)-1] as CommentOrReply; 

Что этот запрос делает пройти любое количество :reply ссылок (начиная от корня «статьи»). Затем он смотрит только на узлы этого пути и возвращает последний элемент (CommentOrReply) и что он был в ответ на (второй последний элемент).

Результат выглядит следующим образом:

+-------------------------------------------------------------------------------------+ 
| InResponseTo        | CommentOrReply       | 
+-------------------------------------------------------------------------------------+ 
| Node[18]{label:"Article"}    | Node[19]{label:"Comment 1"}    | 
| Node[19]{label:"Comment 1"}    | Node[20]{label:"Comment 2 on comment 1"} | 
| Node[19]{label:"Comment 1"}    | Node[21]{label:"Comment 3 on comment 1"} | 
| Node[21]{label:"Comment 3 on comment 1"} | Node[22]{label:"Comment 4 on comment 3"} | 
| Node[18]{label:"Article"}    | Node[23]{label:"Comment 5 on article"} | 
+-------------------------------------------------------------------------------------+ 

Так что, как вы пройти все дерево.

EDIT - для чего это стоит, «переменной соответствия длины пути», который в запросе выше был только этот бит: <-[:reply*1..]- это для меня один из лучших 3-х точек продажи для базы данных графа. Именно то, что графы DB делают очень легко, что большинство ваших других альтернатив, таких как реляционные, превращаются в мучительно болезненные упражнения. Поэтому, если вам нужно сделать что-то подобное (например, при сборке всего дерева), я бы утверждал, что аргументирует наличие DB-графика, потому что вы используете его в своей области фундаментальной силы.

+2

Если вы хотите увидеть еще несколько футляров для деревьев, проверьте их: http://jexp.de/blog/2014/04/importing-forests-into-neo4j/ и http: //blog.bruggen .com/search? q = hierarchy –

+0

Большое спасибо за ваш замечательный и подробный ответ! В настоящий момент я пытаюсь выяснить, как получить этот вложенный хэш, например, в JSON. Но это не вопрос базы данных ...В общем, все выглядит намного быстрее, чем вложенный подход, который вы должны придумать при использовании MySQL. –

+0

Да; в mysql общий шаблон должен иметь только одну таблицу для узлов, которые присоединяются к себе - проверка глубины между 3-4 затем становится очень сложной. – FrobberOfBits

0

Если вложенные деревья являются полностью ориентированными графами и не имеют циклов (т. Е. Направленного ациклического графа = DAG), то вы можете рассмотреть транзитивные методы закрытия в реляционной базе данных. Они позволяют очень быстрые запросы через множественные уровни вложенности & находки нескольких пересечений. У них есть n-квадратная проблема, поэтому есть много строк, но с индексами bigint запросы выполняются быстро.