我刚刚开始使用neo4j,我理解图形和关系的原理,但是我对某些我想建模的结构有点麻烦.我想在编程语言项目中使用它,并存储已解析的源文件的AST.从那里开始,我计划在节点上添加大量额外的数据和关系,以帮助进行分析和工具,但基本的AST仍然有点困难.
制作树的天真方式是简单地遍历AST并将树中的每个节点复制到neo4j中的节点,使用属性来跟踪令牌数据等,然后使用CHILD关系指向子节点.问题是,当我后来想要遍历树时,我需要能够以原始AST的正确顺序执行它,但是开箱即用我不太确定最好的方法.
我有两个基本的方法,我正在考虑我的头脑.一种是只为每个CHILD关系添加一个索引/序数属性.另一种是与第一个孩子建立FIRST关系,并在每个孩子之间建立NEXT关系以保持这种方式.
对于这些方法中的任何一种,它似乎仍然没有任何开箱即用的东西,我可以用它以正确的顺序遍历它.我想如果我做FIRST/NEXT,我可以得到正确的顺序,只要我强迫neo4j始终首先遍历FIRST并进行深度优先搜索.那会有用吗?有没有更好的办法?这似乎是应该更容易处理的东西.
UPDATE
最终我决定使用我的两个想法.子节点与索引属性具有CHILD关系.第一个孩子也有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));
Run Code Online (Sandbox Code Playgroud)
然后,当我真的需要走树时,我可以做到
for(Path path : AST_TRAVERSAL.traverse(astRoot)){
//do stuff here
}
Run Code Online (Sandbox Code Playgroud)
对于我的用例,我实际上并没有在创建后修改树结构本身 - 我只是执行分析并添加更多关系和属性,因此这很容易维护.如果我不得不做更多的修改,那可能会有点工作,特别是如果我想在子关系上维护索引号.因此,对于处于类似情况的其他人来说,这可能需要考虑.
如果我确实进入了一些更可变的东西,我可能会尝试Peter Neubauer建议的集合,并且可能只是创建一个指向节点的OrderedTreeNode类并使用List集合为子节点.