Я только начинаю с neo4j, и я понимаю принципы графика и отношений, но у меня есть небольшие проблемы с определенными структурами, которые я хочу смоделировать.Я хотел использовать его в проекте на языке программирования и сохранить AST в разобранном исходном файле.Оттуда я планирую добавить множество дополнительных данных и связей к узлам, чтобы помочь с анализом и инструментами, но фундаментальный AST все еще немного сложен.
Наивным способом создания дерева было быпросто пройдитесь по AST и скопируйте каждый узел в дереве на узел в neo4j, используя свойства для отслеживания данных токена и т. д., а затем используйте отношение CHILD для указания на дочерние узлы.Проблема в том, что когда я позже захочу пройти по дереву, мне нужно будет сделать это в правильном порядке исходного AST, но из коробки я не совсем уверен, что лучший способ сделать это.
У меня есть два основных подхода, которые я думаю над головой.Один из них - просто добавить индекс / порядковый номер в каждое отношение CHILD.Другой - иметь ПЕРВЫЕ отношения с первым ребенком и СЛЕДУЮЩИЕ отношения между каждым ребенком, чтобы поддерживать порядок таким образом.
Для любого из этих подходов все еще не кажется, что есть что-то нестандартноеможно использовать, чтобы пройти это в правильном порядке.Я думаю, что если я сделаю FIRST / NEXT, я смогу получить правильный порядок, если заставлю neo4j всегда сначала проходить FIRST и выполнять поиск в глубину.Будет ли это работать?Есть ли способ лучше?Это кажется чем-то, что должно быть обработано легче из коробки.
ОБНОВЛЕНИЕ
В конечном счете я решил использовать обе свои идеи.Дочерние узлы имеют отношение CHILD со свойством index.Первый ребенок также имеет отношение FIRST_CHILD.Узлы-братья имеют отношение NEXT_SIBLING, чтобы дать правильный порядок.После этого обход был простым:
//reusable traversal description
final private TraversalDescription AST_TRAVERSAL = Traversal.description()
.depthFirst()
.expand(new OrderedByTypeExpander()
.add(RelType.FIRST_CHILD, Direction.OUTGOING)
.add(RelType.NEXT_SIBLING, Direction.OUTGOING));
, а затем, когда мне действительно нужно было пройтись по дереву, я мог просто сделать
for(Path path : AST_TRAVERSAL.traverse(astRoot)){
//do stuff here
}
Для моего случая использования я на самом деле неизменить саму древовидную структуру после создания - я просто выполняю анализ и добавляю больше связей и свойств, так что это легко поддерживать.Если бы мне пришлось сделать больше изменений, это могло бы быть немного работы, особенно если я хочу сохранить номера индексов на дочерних отношениях.Так что это может быть что-то, что следует учитывать для кого-то другого в подобной ситуации.
Если бы я попал в нечто более изменчивое, я бы, вероятно, попробовал коллекции, предложенные Питером Нойбауэром, и, вероятно, просто создал бы класс OrderedTreeNode, указывающийна узел и использование коллекции List для детей.