我刚开始使用neo4j,我理解图形和关系的原理,但是我在建模特定结构时遇到了一些困难。我想在编程语言项目中使用它,并存储解析源文件的AST。从那里开始,我计划向节点添加大量的附加数据和关系,以帮助分析和工具,但基本的AST仍然有点困难。
制作树的天真方法是简单地遍历AST并将树中的每个节点复制到neo4j中的一个节点,使用属性来跟踪标记数据等,然后使用CHILD关系指向子节点。问题是当我稍后想要遍历树时,我需要能够按照原始AST的正确顺序进行遍历,但是我不确定如何最好地做到这一点。
我想到了两种基本方法。一种是只需为每个CHILD关系添加索引/序数属性。另一种是在第一个子节点之间有一个FIRST关系,在每个子节点之间有一个NEXT关系来维护顺序。
对于这两种方法中的任何一种,似乎都没有现成的东西可以用来以正确的顺序遍历它。我认为,如果我使用FIRST / NEXT,只要强制neo4j始终先遍历FIRST并执行深度优先搜索,我就可以得到正确的顺序。那行吗?有更好的方法吗?这似乎是应该更容易处理的事情。
更新:
最终,我决定使用我的两个想法。子节点具有带有索引属性的CHILD关系。第一个子节点还具有FIRST_CHILD关系。兄弟节点具有NEXT_SIBLING关系以给出正确的顺序。之后,遍历就很容易了。
制作树的天真方法是简单地遍历AST并将树中的每个节点复制到neo4j中的一个节点,使用属性来跟踪标记数据等,然后使用CHILD关系指向子节点。问题是当我稍后想要遍历树时,我需要能够按照原始AST的正确顺序进行遍历,但是我不确定如何最好地做到这一点。
我想到了两种基本方法。一种是只需为每个CHILD关系添加索引/序数属性。另一种是在第一个子节点之间有一个FIRST关系,在每个子节点之间有一个NEXT关系来维护顺序。
对于这两种方法中的任何一种,似乎都没有现成的东西可以用来以正确的顺序遍历它。我认为,如果我使用FIRST / NEXT,只要强制neo4j始终先遍历FIRST并执行深度优先搜索,我就可以得到正确的顺序。那行吗?有更好的方法吗?这似乎是应该更容易处理的事情。
更新:
最终,我决定使用我的两个想法。子节点具有带有索引属性的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));
当我需要遍历树时,只需执行以下操作:
for(Path path : AST_TRAVERSAL.traverse(astRoot)){
//do stuff here
}
针对我的使用情况,在创建树结构后我并不会实际修改树结构本身——我只进行分析并添加更多关系和属性,因此这很容易维护。如果我需要进行更多的修改,特别是如果我想要保持子关系的索引编号,那么这可能需要一些工作。因此,这可能是其他类似情况的人需要考虑的事情。
如果我确实涉及到更多可变内容,我可能会尝试 Peter Neubauer 建议的 collection,并且可能只需创建一个指向节点的 OrderedTreeNode 类,并使用 List collection 用于子节点。