Estoy empezando con neo4j, y entiendo los principios del gráfico y las relaciones, pero estoy teniendo un poco de problemas con ciertas estructuras que quiero modelar. Quería usarlo en un proyecto de lenguaje de programación y almacenar el AST de un archivo fuente analizado. A partir de ahí, planeo agregar una gran cantidad de datos y relaciones adicionales a los nodos para ayudar con el análisis y las herramientas, pero el AST fundamental sigue siendo un poco difícil.Modelando un árbol ordenado con neo4j
La forma ingenua de hacer un árbol sería simplemente caminar el AST y copiar cada nodo en el árbol a un nodo en neo4j, usando propiedades para realizar un seguimiento de los datos de los tokens, etc. y luego usar una relación CHILD para señalar a los nodos hijos. El problema es que, cuando más tarde quiera atravesar el árbol, necesito poder hacerlo en el orden correcto del AST original, pero no estoy seguro de cuál es la mejor manera de hacerlo.
Tengo dos enfoques básicos que estoy pensando en la parte superior de mi cabeza. Una es simplemente agregar una propiedad index/ordinal a cada relación CHILD. El otro es tener una PRIMERA relación con el primer niño y una relación SIGUIENTE entre cada niño para mantener el orden de esa manera.
Para cualquiera de estos enfoques, todavía no parece que haya nada fuera de la caja que pueda usar para recorrer esto en el orden correcto. Creo que si hago FIRST/NEXT, puedo obtener el orden correcto siempre que obligue a neo4j a recorrer primero FIRST primero y hacer una primera búsqueda en profundidad. Funcionaría eso? ¿Hay una mejor manera? Esto parece algo que debería manejarse más fácilmente de la caja.
ACTUALIZACIÓN
En última instancia, decidí utilizar mis dos ideas. Los nodos secundarios tienen una relación NIÑO con una propiedad índice. El primer hijo también tiene la relación FIRST_CHILD. Los nodos hermanos tienen una relación NEXT_SIBLING para proporcionar el orden correcto. Después de eso, el recorrido fue fácil:
//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));
y luego cuando en realidad tenía que recorrer el árbol tan sólo pudiera hacer
for(Path path : AST_TRAVERSAL.traverse(astRoot)){
//do stuff here
}
Por mi caso de uso, que en realidad no modificar la estructura de árbol después de la creación, solo realizo el análisis y agrego más relaciones y propiedades, por lo que es fácil de mantener. Si tuviera que hacer más modificaciones, podría ser un poco de trabajo, especialmente si quiero mantener los números índices en las relaciones infantiles. Entonces eso podría ser algo para considerar para alguien más en una situación similar.
Si tuviera algo más mutable, probablemente probaría las colecciones sugeridas por Peter Neubauer, y probablemente solo crearía una clase OrderedTreeNode apuntando a un nodo y usando la colección List para niños.
gracias, estoy buscando y creo que podría usar algunas de estas cosas en algún momento. Por ahora, debido a que no hago muchas modificaciones a los nodos después de la creación, creo que me quedaré con FIRST/NEXT, pero si tengo requisitos más complicados, definitivamente tendré que intentarlo. . Un poco más de documentación sería útil, pero entiendo que es un trabajo en progreso y se ve muy bien hasta ahora, gracias. –